Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two Panini Functions, Two Sets of Options: Identical Output #81

Closed
ethanbeyer opened this issue Aug 29, 2016 · 10 comments
Closed

Two Panini Functions, Two Sets of Options: Identical Output #81

ethanbeyer opened this issue Aug 29, 2016 · 10 comments

Comments

@ethanbeyer
Copy link

I'm working on a project where I am creating emails using Foundation Emails, but the compiled output will need to be piped to other parts of its parent project as layouts and views for use within Laravel.

Consider the following:

gulp.task('build:portal',
    gulp.series(
      clean,
      resetPages, 
      sass,
      images,
      layouts,
      views
));

function layouts()
{
  return gulp.src('./src/pages/**/*.html')
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/laravel-layout-layouts/',          // using one layout here
      partials: 'src/partials/',
      helpers: 'src/helpers/'
    }))
    .pipe(inky())
    .pipe(gulp.dest('dist/layouts'));
}

function views()
{
  return gulp.src('./src/pages/**/*.html')
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/laravel-view-layouts/',          // and a different one here
      partials: 'src/partials/',
      helpers: 'src/helpers/'
    }))
    .pipe(inky())
    .pipe(gulp.dest('dist/views'));
}

The layouts: options obviously differ in the functions.

Both layouts() and views() use the same pages as their source, but are piping the output to different destinations by way of different layouts -- but the output is exactly the same for both.

  • If views() is called in the gulp.series() first, the output of layouts() will be the same as views().
  • If layouts() is called first, the output of views() will be the same as layouts().

As I'm writing this, I'm thinking that maybe the issue is that panini is technically being used twice within the same gulp.task() - but based on the fact that I am passing an options object to it, I would expect it respect those values.

Please advise!

@ethanbeyer
Copy link
Author

I tried changing the functions to look like this:

function layouts()
{
  panini.refresh();
  return gulp.src('./src/pages/**/*.html')
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/laravel-layout-layouts/',
      partials: 'src/partials/',
      helpers: 'src/helpers/'
    }))
    .pipe(inky())
    .pipe(gulp.dest('dist'));
}

function views()
{
  panini.refresh();
  return gulp.src('./src/pages/**/*.html')
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/laravel-view-layouts/',
      partials: 'src/partials/',
      helpers: 'src/helpers/'
    }))
    .pipe(inky())
    .pipe(gulp.dest('dist/views'));
}

And I'm still getting the mirrored output issue. I have no idea why this doesn't work.

@valentinceaprazaru
Copy link

@ethanbeyer hi, have you managed to solve this issue?

@ethanbeyer
Copy link
Author

ethanbeyer commented Oct 18, 2016

Hey @valentinceaprazaru, I never solved why the output was identical even though it wasn't supposed to be, but I did manage to complete a work-around, which essentially was to break this into two different gulp tasks. It seemed that if the two sub-tasks were called in the same stream, the second would just use the cached output from the first. There is no way that I could see of completely flushing the cache of the task while the task was running, so my final code looked like this:

gulp.task('build:layouts',
  gulp.series( clean, cleanLaravel, layouts, sass, inline, niceLookingHtml )
);

// Views for Laravel
gulp.task('build:views',
  gulp.series( views, copyCssForViews, inline, niceLookingHtml )
);

// cleaning folders that need to be reinstantiated on generation
function cleanLaravel(done) {
  rimraf(tempLaravelDir, done);
}

// Create Laravel Layouts
function layouts()
{
  return gulp.src( emailsToExport )
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/laravel-layouts/',
      partials: 'src/partials/',
      helpers: 'src/helpers/'
    }))
    .pipe(inky())
    .pipe(gulp.dest('dist'));
}

// Create Laravel Views
function views()
{
  return gulp.src( emailsToExport )
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/laravel-views/',
      partials: 'src/partials/',
      helpers: 'src/helpers/'
    }))
    .pipe(inky())
    .pipe(gulp.dest('dist/views'));
}

// Prevent inlining errors by duplicating the CSS into the views dir also.
function copyCssForViews()
{
  return gulp.src('dist/css/*.css')
    .pipe(gulp.dest('dist/views/css'));
}

Lastly - creating a gulp task that ran both build:layouts and then build:views resulted in the same error I originally opened the issue about. So the final step was adding this to the package.json file:

"scripts": {
    "makelaravel": "gulp build:layouts --production; gulp build:views --production; gulp build:portal --production; gulp build --production"
  },

So then running $ npm run makelaravel in the terminal ran all the tasks in order, as their own tasks, and that allowed me to get the expected output.

I hope this helps in some way!

@thardyman
Copy link

This is a big issue for me too. Thanks @ethanbeyer for a solution. Ideally panini.refresh() would resolve this.

@ethanbeyer
Copy link
Author

I tried everything I could think of regarding panini.refresh() and felt that that function wasn't doing its full job.

@gakimball
Copy link
Contributor

Hey there! I know this is a pretty old issue, but I see what's going on. Like you said, Panini does indeed "cache" its instance—it's a singleton, so when you write var panini = require('panini');, you're getting one instance of Panini, which can only hold one set of options.

If you look at the source code for the panini() function, you can see that it makes a new Panini renderer, does some setup, and then returns a .render() function, which is what's actually passed to Gulp.

By recreating this, you can have separate instances of Panini in your Gulpfile. This isn't super elegant, so maybe it's something that could be addressed in a future version.

var Panini = require('panini').Panini;
var panini = new Panini({ /* options */ });
panini.loadBuiltinHelpers();
panini.refresh();

function pages() {
  gulp.src('src/pages/**/*.html')
    .pipe(panini.render())
    .pipe(gulp.dest('dist'));
}

Let me know if y'alls have any questions. :)

@ethanbeyer
Copy link
Author

WOW! Thank you! That is an itch I've wanted scratched for literal months. Very helpful. Thanks again!

@gakimball
Copy link
Contributor

No worries! 🙌

@AdamPflug
Copy link

Just ran into this issue myself and spun on it for a while as well. It seems it would be trivial (I could create a pull request if you want) to remove this singleton behavior from the code - any idea why this is currently being done? I can't think of a single situation where the current behavior would be desired or expected.

If it's just for refresh() purposes it'd be pretty easy to keep track of all the instances that get created and refresh all of them if that's a requirement.

@gakimball
Copy link
Contributor

@AdamPflug It's an ease of use thing mainly. I'd prefer to keep the existing behavior as a default since v1 is basically EOL, but if you want to add a create() function to the main export I can merge it in. It would probably look something like this.

marvinhuebner added a commit to bergwerk/magento2-frontools that referenced this issue Nov 16, 2018
…to refresh the partials in all renderers

Panini exports an singleton, through that it holds all options and they can not be overwritten. This change adds a new panini instance for each task to hold it's own options.

Panini is patched because Handlebars is also a singleton, so the partials will be overwritten. You can find more infos here: foundation/panini#81 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants