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

A tool to insert a section in between existing ones #478

Open
varya opened this issue Feb 16, 2015 · 1 comment
Open

A tool to insert a section in between existing ones #478

varya opened this issue Feb 16, 2015 · 1 comment
Labels
Milestone

Comments

@varya
Copy link
Contributor

varya commented Feb 16, 2015

KSS requires to provide section reference numbers in comments. It's OK but when I need to add another block in between of existing ones, this makes me shift all the sections with bigger numbers. Sometimes it's a lot of work. It would be nice to have a tool which makes this automatically.
This tool should go as a CLI and gulp-plugin.

In out project we came up with a gulp task. It can be run with parameters like gulp styleguide:new-section --name=NewSection --order=6.2.1. It shift the sections after the given number and adds new section in the existing files. The code is shitty and does not consider many cases (like multiple line parameters). But I hope it will give you an idea how to move on.

'use strict';

var gulp;
var gutil = require('gulp-util');
var gonzales = require("gonzales-pe");
var minimist = require("minimist");
var through = require("through2");

module.exports = function registerTasks(g) {
    gulp = g;
    Object.keys(tasks).forEach(function(task) {
        gulp.task(task, tasks[task]);
    });
}

var tasks = {

    'styleguide:new-section': newSection

}

function newSection() {
    var args = minimist(process.argv.slice(2));

    var params = {
      name: args['name'] || args['n'],
      order: args['order'] || args['o']
    };

    var sourcePath = "public_html/scss";
    var source = sourcePath + "/**/*.scss";

    if (!params.name) {
      gutil.beep();
      gutil.log(gutil.colors.red('Define name with --name=my-name'));
      return;
    }

    if (!params.order) {
      gutil.beep();
      gutil.log(gutil.colors.red('Define name with --order=1.2.3'));
      return;
    }

    params.order = params.order.toString();

    // TODO: if order is not given, place into the last one
    // TODO: Check ref number parameter with regexp

    function getPreviousSection(section) {
      var previousSectionArray = section.split('.');
      previousSectionArray[previousSectionArray.length - 1] -= 1;
      if (previousSectionArray[previousSectionArray.length - 1] === 0) {
        previousSectionArray.pop();
      }
      return previousSectionArray.join('.');
    }

    function changeNumber(section) {

        var filesBuffer = {};

        var stream = through.obj(function(file, enc, cb) {

            var content = file.contents.toString('utf8');
            var syntax = 'scss';
            var ast = gonzales.parse(content, { syntax: syntax });
            var isKssMarkupBlock = /Styleguide [0-9]+/;

            function isLess(left, right) {
                left = left.split('.');
                right = right.split('.');

                var l = false;

                for(var i = 0; i< Math.max(left.length, right.length); i++ ) {
                    if (parseInt(left[i]) < parseInt(right[i])) {
                        l = true;
                        break;
                    }
                    if (parseInt(left[i]) > parseInt(right[i])) {
                        l = false;
                        break;
                    }
                }
                return l;

            }

            function ifBelongsToParent(parentSection, section) {

                var belongs = true;

                parentSection = parentSection && parentSection.split('.');
                section = section.split('.');

                parentSection && parentSection.forEach(function(val, n) {
                    if (val !== section[n]) {
                        belongs = false;
                    }
                });

                return belongs;

            }

            function increaseSection(section, diff) {
                section = section.split('.');
                var last = section.pop();
                section.push(parseInt(last) + diff);
                return section.join('.');
            }

            function newStream(content) {
             var stream = through();
             stream.write(content);
             return stream;
            }

            ast.map(function(declaration){
                // Take only comments
                if (
                    declaration.type !== 'commentSL' &&
                    declaration.type !== 'commentML'
                  ) return;
                // Skip everything which is not Styleguide reference
                if (!isKssMarkupBlock.test(declaration.content))
                   return;

                // Increase all the sections after the given one
                var matchRegexp = /(Styleguide )([0-9]+(\.[0-9]+)*)/;
                var match = declaration.content.match(matchRegexp);
                var currentNumber = match[2];

                // Skip sections with less reference number
                if (isLess(currentNumber, section))
                    return;

                // Skip everything which does not belong parent section
                var parentSection = section.split('.');
                parentSection.pop();
                parentSection = parentSection.join('.');

                if (!ifBelongsToParent(parentSection, currentNumber))
                    return;

                // Skip parent section itself
                if (parentSection === currentNumber)
                    return;

                // Increase everything with +1
                var newVal = increaseSection(currentNumber, 1);

                declaration.content = declaration.content.replace(matchRegexp, '$1' + newVal);

            });

            var newContent = new Buffer(ast.toCSS(syntax));
            file.contents = Buffer.concat([newContent]);

            this.push(file);
            cb();
        });

        return stream;
    }

    function insertSection(name, reference) {
        var inserted = false;
        var stream = through.obj(function(file, enc, cb) {
            // Content of the new Section
            var sectionContent =[
                '// ' + params.name,
                '//',
                '// Styleguide ' + params.order
            ];

            var previousSection = getPreviousSection(params.order);
            // Paste new section after a blog of previous section
            var content = file.contents.toString('utf8');
            var syntax = 'scss';
            var ast = gonzales.parse(content, { syntax: syntax });

            var isKssMarkupBlock = /Styleguide [0-9]+/;
            var commentBlockStarted = false;
            var startLookForSection = false;

            ast.map(function(declaration) {
                if (inserted) {
                    return;
                }
                if (declaration.type === 'commentSL' && declaration.content === ' Styleguide ' + previousSection) {
                    startLookForSection = true;
                    return;
                }
                if (!startLookForSection) {
                    return;
                }
                if (declaration.type === 'commentSL' && commentBlockStarted === false) {
                    commentBlockStarted = declaration;
                }
                if (
                    declaration.type !== 'commentSL'
                    && commentBlockStarted
                    && declaration.content !== '\n'
                    && declaration.content !== '\n\n'
                    ) {
                    commentBlockStarted = false;
                }
                if (
                      commentBlockStarted &&
                      declaration.type === 'commentSL' &&
                      isKssMarkupBlock.test(declaration.content)
                    ) {
                    // So, this was a KSS block, we need to place before commentBlockStarted

                    // TODO: rewrite normally when ast.insert is implemented
                    commentBlockStarted.content = '\n\n\n' + sectionContent.join('\n') + '\n\n//' + commentBlockStarted.content;
                    inserted = true;
                }
            });

            var endOfFile = ''
            if (inserted === false && startLookForSection === true) {
                // need to add by the end of the file
                endOfFile = '\n\n' + sectionContent.join('\n');
            }

            var newContent = new Buffer(ast.toCSS(syntax));
            endOfFile = new Buffer(endOfFile);
            file.contents = Buffer.concat([newContent, endOfFile]);
            this.push(file);
            cb();

        });
        return stream;
    }

    // Change all the numbers after giving one
    gulp.src(source)
        .pipe(changeNumber(params.order))
        .pipe(insertSection(params.name, params.order))
        .pipe(gulp.dest(sourcePath));
}
@varya varya added the feature label Feb 16, 2015
@cyberixae cyberixae modified the milestone: Soon Mar 19, 2015
@dlangston
Copy link

I am having this problem when using this feature
#1073 (comment)
Has anyone else seen this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants