slara / generator-reveal

Yeoman generator for Reveal.js
MIT License
429 stars 52 forks source link

Generate missing slide files using list.json #56

Closed millette closed 9 years ago

millette commented 10 years ago

I'm using reveal (and your generator, thanks!) to build a rather large presentation. Because I'm using subsections, I find it easier to start by editing list.json itself with filenames and to give it structure. I'd like to use the info in the list.json file to generating missing slides.

I will probably tackle this for my own use, but also wanted to know if there was a more general interest in this feature.

millette commented 10 years ago

For now, I'm using the following script I named create-missing.js, only tested on Debian GNU/Linux:


/*
 * Create missing slide files in ./slides/
 * based on ./slides/list.json
 * Missing or empty slide files are created with a title based on their file name
 * File contents are hard-coded in the writeFile() function
 * and support markdown and html, based on file name extension
 *
 * Run with: node (or nodejs) create-missing.js
 * Not at all integrated with grunt or the yeoman generator (yet)
 */ 

(function() {
    'use strict';

    var fs = require('fs'),
        path = require('path');

    // basé sur grunt.file
    // Read a file, return its contents.
    function read(filepath) {
      try {
        return fs.readFileSync(filepath, 'utf8');
      } catch(e) {
        throw {a:'Unable to read "' + filepath + '" file (Error code: ' + e.code + ').', b:e};
      }
    };

    // basé sur grunt.file
    // Read a file, parse its contents, return an object.
    function readJSON(filepath) {
      var src = read(filepath);

      try {
        return JSON.parse(src);
      } catch(e) {
        throw {a:'Unable to parse "' + filepath + '" file (Error message: ' + e.message + ').', b:e};
      }
    };

    function readList(filepath) {
        var content = readJSON('slides/list.json'),
            section, subsection, filenames = {}, ret = [], i;

        for (section = 0; section < content.length; ++section) {
            if ('string' === typeof content[section]) {
                filenames[content[section]] = true;
            } else {
                for (subsection = 0; subsection < content[section].length; ++subsection) {
                    if ('string' === typeof content[section][subsection]) {
                        filenames[content[section][subsection]] = true;
                    } else if (content[section][subsection].filename) {
                        filenames[content[section][subsection].filename] = true;
                    }
                }
            }
        }

        for (i in filenames) {
            ret.push('slides/' + i);
        }

        return ret;
    }

    function writeFile(fd) {
        // nom du fichier selon le file descriptor
        fs.readlink('/proc/self/fd/' + fd, function(err, fn) {
            var str, buffer,
                extension = path.extname(fn),
                // str.replace(...) ne remplace que la première occurence
                bn = path.basename(fn, extension).split('-').join(' ');

            if ('.html' === extension) {
                str = '<h2>' + bn + '</h2>\n\n<p>Bla</p>\n\n<aside class="notes">\nPut your speaker notes here. You can see them pressing "s".\n</aside>\n';
            } else if ('.md' === extension) {
                str = '## ' + bn + '\n\nBlabla\n\nnote:\nPut your speaker notes here. You can see them pressing "s".\n';
            } else {
                console.log("format de fichier inconnu: " + fn);
                return;
            }

            buffer = new Buffer(str);
            fs.write(fd, buffer, 0, buffer.length, null, function(err, written, buffer) {
                fs.close(fd, function(err) {
                    if (err) {
                        console.log('erreur avec ' + fn);
                        console.log(err);
                    } else {
                        console.log(fn + ': créé.');
                    }
                });
            });
        });
    }

    function createIf(fn, flags) {
        // on crée un fichier s'il n'existe pas
        fs.open(fn, flags || 'wx', function(err, fd) {
            if (err) {
                // il existe déjà? on vérifie s'il est vide
                fs.stat(err.path, function(err, stats) {
                    if (stats.size) {
//                        console.log(fn + ': le fichier existe et n\'est pas vide');
                    } else {
                        // il est vide, mettons-y du contenu
                        createIf(fn, 'w');
                    }
                });
            } else {
                writeFile(fd);
            }
        });
    }

    function createIfMissing(filepath) {
        var r, filenames = readList(filepath);

        for (r = 0; r < filenames.length; ++r) {
            createIf(filenames[r]);
        }
    }

    console.log('hop');
    createIfMissing('slides/list.json');
}());
slara commented 10 years ago

Hi @millette! I think this could be a nice feature to have. I'm not really sure on how we could implement it...

janraasch commented 10 years ago

I think this may blow the scope of the generator, but, if you can come up with a pull request that implements this as a grunt task we can give it a try. Also, seems like a lot of this code should be simplified using some of node's built-in helpers, e.g. for writing and reading files.

millette commented 10 years ago

Indeed, the code could use lots of improvements as it stands, but since the idea was to eventually turn it into a grunt task, I didn't spend any time on that. Instead of using fs.open with the wx flag, I could probably test for the file's existence.

I don't know when, but I will give it a shot (rewrite for grunt - which I haven't coded for yet) and keep you posted.

janraasch commented 10 years ago

Cool :+1:

janraasch commented 9 years ago

No update in 3 months. Closing this for now.