SassDoc / generator-sassdoc-theme

Yeoman generator that scaffolds out a SassDoc theme.
The Unlicense
3 stars 1 forks source link

handlebars engine, ctx.data goes from array of objects to 'true' #22

Closed aristretto closed 9 years ago

aristretto commented 9 years ago

My Node's a little rusty, and I may be looking at this with a tired brain / pair of eyes. For the life of me I can't figure out why ctx.data goes from an array of objects (as seen below);


// in https://github.com/SassDoc/generator-sassdoc-theme/blob/master/templates/handlebars/_index.js#L149
// console.log(ctx);
// return theme.apply(this, arguments);
...
displayTheme: 'sassdoc-theme-foo',
  src: [ 'source/features/**/*.scss' ],
  data: 
   [ { description: '<p>lorem ipsum dolor sit amet</p>\n',
       commentRange: [Object],
       context: [Object],
       access: 'public',
       example: [Object],
       group: [Object],
       require: [],
       file: [Object],
       groupName: [Object] },
     { description: '<p>lorem ipsum dolor sit amet</p>\n',
       commentRange: [Object],
       context: [Object],
       access: 'public',
       example: [Object],
       group: [Object],
       require: [],
       file: [Object],
       groupName: [Object] },
     byGroupAndType: { undefined: [Object] } ],
  load: [Function: load],
  loadObject: [Function: loadObject],
...

to true when it finally reaches my index.handlebars template (as seen below:)


// this debug helper shows what the context is in `index.handlebars`

var theme = themeleon(__dirname, function (t) {
  t.copy('assets');

  var options = {
    helpers: {
      'debug': function() {
        console.log("Current Context");
        console.log("====================");
        console.log(this);
      }
    }
  };
  t.handlebars('views/index.handlebars', 'index.html', options);
});

// "this.data" === true now
// ...
// displayTheme: 'sassdoc-theme-masq',
//  src: [ 'source/features/**/*.scss' ],
//  data: true,
//  load: [Function: load],
//  loadObject: [Function: loadObject],
// ...

The end result is I can't loop over anything in index.handlebars.

aristretto commented 9 years ago

Spent a little while debugging, and my wild goose chase led me to this line of Handlebars: https://github.com/components/handlebars.js/blob/master/handlebars.js#L2204

It seems like something in Handlebars is somehow setting an object called options.data to true. I debugged the following line of consolidate.js with console.log statements

https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js#L655

console.log(options.data);
fn(null, tmpl(options));
console.log(options.data);

first console.log gives me a correct data array second console.log gives me true.

Going to give up for the day, but it seems like a name collision is the root of this bug. This works:

consolidate.js

options._data = options.data
fn(null, tmpl(options));

Handlebars:

{{!-- in my handlebar template I can now access and loop over "data" --}}
{{_data}}

I'll open an issue in consolidate.js as this seem to be more of an issue in that project, less so Sassdoc. Just thought I'd give an update. Feel free to close this issue out if you'd like.

In hindsight this actually does seem like an issue that can be more easily solved by an update to SassDoc.

I'll open a PR with a suggested edit soon.

aristretto commented 9 years ago

https://github.com/SassDoc/generator-sassdoc-theme/pull/23

valeriangalliat commented 9 years ago

Hey @aristretto, thank you for reporting this issue.

After having a quick look, I think it may be related to this.

However, I'm unable to reproduce the bug on my side.

// index.js
var themeleon = require('themeleon')()

themeleon.use('consolidate')

module.exports = themeleon(__dirname, function (t) {
  var options = {
    helpers: {
      debug: function () {
        console.log(this)
      },
    },
  }

  t.handlebars('index.hbs', 'index.html', options)
})
{{! index.hbs }}
{{#debug}}
{{/debug}}

{{#each data}}
  {{description}}
{{/each}}
// package.json
{
  "dependencies": {
    "handlebars": "^3.0.1",
    "themeleon": "^3.0.0"
  }
}

For me, the {{#debug}} shows a proper data array, and the output index.html contains the description of all items.

Did I misunderstood something?

aristretto commented 9 years ago

Did I misunderstood something?

No, that looks about right. However, i tried a fresh install, generated a new theme with:

$ yo sassdoc-theme sassdoc-theme-counsyl --init --theme-engine=handlebars

and still have had no luck. data still == true.

valeriangalliat commented 9 years ago

Well that's odd, I just tried with the Yeoman generator but still, I can loop over items without problem, nothing like a true data…

I found a few minor bugs with the default Handlebars template however, but nothing related to this actual issue.

Also note I'm testing the theme by rendering sassdoc-theme-default's scss folder… not sure it can change something but can you try to render this folder with your theme too? And with my debug theme from the previous post?

Otherwise, could you share your exact theme (index.js, package.json, and views folder) so I can investigate further? Also what's your Node/io.js version?

aristretto commented 9 years ago

I ran my grunt task over sassdoc-theme-default's scss folder and got the same results, {data: true}. I tried my "fix" of data -> _data and that worked.

Also FYI, the SassDoc syntax used in the default theme's scss folder is deprecated (uses /** style comments instead of ///. I tried running sassdoc over both styles just in case. /** failed to parse anything, and /// resulted in {data: true}.

$ node -v
v0.10.26
$ npm list io.js
 project@0.5.5 /Users/albert/work/project
└── (empty)
// package.json
{
  "name": "sassdoc-theme-foo",
  "description": "Counsyl SassDoc theme",
  "version": "0.1.0",
  "keywords": [
    "sassdoc-theme"
  ],
  "dependencies": {
    "extend": "^1.0.0",
    "handlebars": "^3.0.1",
    "sassdoc-extras": "^2.0.0",
    "themeleon": "^3.0.0"
  },
  "engines": {
    "node": ">=0.10.0"
  },
  "devDependencies": {
    "bluebird": "^2.9.24",
    "fs-extra": "^0.18.0",
    "grunt": "^0.4.5",
    "grunt-autoprefixer": "^3.0.0",
    "grunt-browser-sync": "^2.1.1",
    "grunt-contrib-imagemin": "^0.9.4",
    "grunt-contrib-sass": "^0.9.2",
    "grunt-contrib-uglify": "^0.8.1",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-newer": "^1.1.0",
    "grunt-sassdoc": "^2.0.0",
    "grunt-svgmin": "^2.0.1",
    "load-grunt-tasks": "^3.1.0",
    "time-grunt": "^1.1.0"
  }
}
// index.js

var themeleon = require('themeleon')().use('consolidate')
  , extend    = require('extend')
  , extras    = require('sassdoc-extras')
  , theme     = themeleon(__dirname, function (t) {

  t.copy('assets');

  var options = {
    helpers: {
      debug: function(){ console.log(this); }
    }
  };

  t.handlebars('views/index.hbs', 'index.html', options);
});

module.exports = function (dest, ctx) {
  var def = {
    display: {
      access: ['public', 'private'],
      alias: false,
      watermark: true,
    },
    groups: {
      'undefined': 'General',
    },
    'shortcutIcon': 'http://sass-lang.com/favicon.ico',
  };

  ctx.groups  = extend(def.groups, ctx.groups);
  ctx.display = extend(def.display, ctx.display);
  ctx         = extend({}, def, ctx);

  extras.markdown(ctx);
  extras.display(ctx);
  extras.groupName(ctx);

  ctx.data.byGroupAndType = extras.byGroupAndType(ctx.data);

  return theme.apply(this, arguments);
};
{{!-- views/index.hbs --}}

<!DOCTYPE html>
<html lang="en">
  <head>
    <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="assets/css/styleguide.css">
  </head>
  <body>

    {{#debug}}{{/debug}}

    <div class="panel panel--docs">
      {{! 1. Loop over the groups in `data.byGroupAndType` }}
      {{#each data.byGroupAndType }}
      <section>
        {{! Retrieve group alias if any (else group name) }}
        <h1>{{ groups.[@key] }}</h1>
        {{! 2. Loop over the types in the current group }}
        {{#each this }}
        {{! If items to be displayed in type }}
        {{#if this }}
        <section>
          <h2>{{ @key }}</h2>
          {{! 3. Loop over the items in the current type }}
          {{#each this }}
          {{! At this point it is up to you to display whatever you want from your items. }}
          <h3>{{ context.name }}</h3>
          {{description}}
          {{/each}}
        </section>
        {{/if}}
        {{/each}}
      </section>
      {{/each}}
    </div>
  </body>
</html>
pascalduez commented 9 years ago

Also FYI, the SassDoc syntax used in the default theme's scss folder is deprecated (uses /\ style comments instead of ///.

The default theme documented items are in scss/utils i.e. functions, mixins, variables. They properly use the 3 slashes notation.

valeriangalliat commented 9 years ago

I can reproduce the bug, I'm trying to track it down.

valeriangalliat commented 9 years ago
{{#debug}}{{/debug}}

{{#each data.byGroupAndType}}
  {{#each this}}
    {{#if this}}
      {{@key}}
    {{/if}}
  {{/each}}
{{/each}}

In the above example, data is true.

Now if I remove the {{@key}}, data is a proper array (with byGroupAndType).

{{#debug}}{{/debug}}

{{#each data.byGroupAndType}}
  {{#each this}}
    {{#if this}}
    {{/if}}
  {{/each}}
{{/each}}

It's more or less a feature. At least Handlebars overwrite the data variable when it finds some @ access.

@pascalduez What do you think about having the variable called _data for Handlebars only (like in @aristretto's PR)?

It will mean we can't refactor the generator templates because the Handlebars one will have this hack added…

aristretto commented 9 years ago

It will mean we can't refactor the generator templates because the Handlebars one will have this hack added…

Adding a short explanation might be sufficient, just so people don't end up on a wild goose chase tracking this down.

The default theme documented items are in scss/utils i.e. functions, mixins, variables. They properly use the 3 slashes notation.

Woops, I meant the scss folder in the generated theme. Weird though, my generated scss dir has /** style comments, but I see here that the correct style is used. ¯_(ツ)_/¯

pascalduez commented 9 years ago

Adding a short explanation might be sufficient, just so people don't end up on a wild goose chase tracking this down.

With proper documentation I think it's fine.

Weird though, my generated scss dir has /\ style comments, but I see here that the correct style is used.

There was a commit on develop that got merged yesterday ;-)

aristretto commented 9 years ago

:+1: thanks for taking the time to debug with me!

pascalduez commented 9 years ago

Fixed in 0.2.2 Thanks for reporting and debugging !