text: var Parser = require('../../src/remark/parser');
  
  describe('Parser', function () {
  
    describe('splitting source into correct number of slides', function () {
      it('should handle single slide', function () {
        parser.parse('1').length.should.equal(1);
      });
  
      it('should handle multiple slides', function () {
        parser.parse('1\n---\n2\n---\n3').length.should.equal(3);
      });
  
      it('should treat empty source as single slide', function () {
        parser.parse('').length.should.equal(1);
      });
  
      it('should ignore slide separator inside fences', function () {
        parser.parse('1\n---\n```\n---\n```\n---\n3').length.should.equal(3);
      });
  
      it('should ignore slide separator inside content class', function () {
        parser.parse('1\n---\n2\n.class[\n---\n]\n---\n3').length.should.equal(3);
      });
  
      it('should split slides correctly when more than one backtick is used for inline code', function(){
        parser.parse('1\n---\nTest inline ``code``\n---\n3 More `code`').length.should.equal(3);
      });
  
      it('should split slides correctly when more than one backtick is used for inline code followed by code block', function(){
        parser.parse('1\n---\nTest inline ``code``\n---\n```\ncode\n```').length.should.equal(3);
      });
    });
  
    describe('mapping source to corresponding slides', function () {
      it('should handle single slide', function () {
        parser.parse('1')[0].content.should.eql(['1']);
      });
  
      it('should handle multiple slides', function () {
        var slides = parser.parse('1\n---\n2\n---\n3');
  
        slides[0].content.should.eql(['1']);
        slides[1].content.should.eql(['2']);
        slides[2].content.should.eql(['3']);
      });
  
      it('should ignore excluded slides', function () {
        var slides = parser.parse('1\n---\nexclude: true\n2\n---\n3');
  
        slides[0].content.should.eql(['1']);
        slides[1].content.should.eql(['3']);
      });
  
      it('should handle empty source', function () {
        parser.parse('')[0].content.should.eql(['']);
      });
    });
  
    describe('parsing notes', function () {
      it('should map notes', function () {
        parser.parse('content\n???\nnotes')[0].notes.should.eql(['notes']);
      });
  
      it('should extract notes from source', function () {
        parser.parse('content\n???\nnotes')[0].content.should.eql(['content']);
      });
    });
  
    describe('parsing code', function () {
      it('should include code', function () {
        var slides = parser.parse('1\n\n    code\n2\n---\n3\n\n    code\n4');
  
        slides[0].content.should.eql(['1\n\n    code\n2']);
        slides[1].content.should.eql(['3\n\n    code\n4']);
      });
  
      it('should ignore content class inside code', function () {
        parser.parse('some code\n\n    .class[x]')[0].content.should.eql(['some code\n\n    .class[x]']);
      });
    });
  
    describe('parsing fences', function () {
      it('should include fences', function () {
        var slides = parser.parse('1\n```\n\n```\n2\n---\n3\n```\n\n```\n4');
  
        slides[0].content.should.eql(['1\n```\n\n```\n2']);
        slides[1].content.should.eql(['3\n```\n\n```\n4']);
      });
  
      it('should ignore content class inside fences', function () {
        parser.parse('```\n.class[x]\n```')[0].content
          .should.eql(['```\n.class[x]\n```']);
      });
    });
  
    describe('parsing link definitions', function () {
      it('should extract link definitions', function () {
        parser.parse('[id]: http://url.com "title"')[0].links.id
          .should.eql({ href: 'http://url.com', title: 'title' });
      });
    });
  
    describe('parsing macros', function () {
      it('should expand macro', function () {
        var macros = {
          sum: function () {
            var result = 0;
            for (var i = 0; i < arguments.length; ++i) {
              result += parseInt(arguments[i], 10);
            }
            return result;
          }
        };
        parser.parse('a ![:sum 1, 2, 3] b', macros)[0].content
          .should.eql(['a 6 b']);
      });
  
      it('should expand macro recursively', function () {
        var macros = {
          upper: function () {
            return this.toUpperCase();
          },
          addupper: function () {
            return "![:upper](word)";
          }
        };
        parser.parse('Uppercase => ![:addupper](word)', macros)[0].content
          .should.eql(['Uppercase => WORD']);
      });
    });
  
    describe('parsing content classes', function () {
      it('should convert block content classes', function () {
        parser.parse('1 .class[\nx\n] 2')[0].content
          .should.eql([
            '1 ',
            { class: 'class', block: true, content: ['\nx\n'] },
            ' 2'
          ]);
      });
  
      it('should convert inline content classes', function () {
        parser.parse('1 .class[x] 2')[0].content
          .should.eql([
            '1 ',
            { class: 'class', block: false, content: ['x'] },
            ' 2'
          ]);
      });
  
      it('should convert multiple classes', function () {
        parser.parse('1 .c1.c2[x]')[0].content
          .should.eql([
            '1 ',
            { class: 'c1 c2', block: false, content: ['x'] }
          ]);
      });
  
      it('should ignore unclosed inline content classes', function () {
        parser.parse('1 .class[x 2')[0].content.should.eql(['1 .class[x 2']);
      });
  
      it('should ignore unclosed block content classes', function () {
        parser.parse('1 .class[\n2')[0].content.should.eql(['1 .class[\n2']);
      });
  
      it('should parse source in content classes', function () {
        parser.parse('.c1[.c2[x]]')[0].content
          .should.eql([
            { class: 'c1', block: false, content:
              [{ class: 'c2', block: false, content: ['x'] }]
            }
          ]);
      });
    });
  
    describe('identifying continued slides', function () {
      it('should not identify normal, preceding slide as continued', function () {
        parser.parse('1\n--\n2\n---\n3')[0].properties.continued.should.equal('false');
      });
  
      it('should identify continued slide as continued', function () {
        parser.parse('1\n--\n2\n---\n3')[1].properties.continued.should.equal('true');
      });
  
      it('should not identify normal, succeeding slide as continued', function () {
        parser.parse('1\n--\n2\n---\n3')[2].properties.continued.should.equal('false');
      });
    });
  
    describe('parsing slide properties', function () {
      it('should map single property', function () {
        parser.parse('name: a\n1')[0].properties.name.should.equal('a');
      });
  
      it('should map multiple properties', function () {
        var slides = parser.parse('name: a\nclass:b\n1');
  
        slides[0].properties.name.should.equal('a');
        slides[0].properties['class'].should.equal('b');
      });
  
      it('should allow properties with no value', function () {
        var slides = parser.parse('a:   \n\nContent.');
        slides[0].properties.should.have.property('a', '');
      });
  
      it('should extract properties from source', function () {
        parser.parse('name: a\nclass:b\n1')[0].content.should.eql(['\n1']);
      });
    });
  
    describe('parsing content that is indented', function () {
      it('should handle leading whitespace on all lines', function () {
        var slides = parser.parse('      1\n      ---\n      2\n      ---\n      3');
  
        slides[0].content.should.eql(['1']);
        slides[1].content.should.eql(['2']);
        slides[2].content.should.eql(['3']);
      });
  
      it('should ignore empty lines when calculating whitespace to trim', function () {
        var slides = parser.parse('      1\n\n      1\n      ---\n      2\n      ---\n      3');
  
        slides[0].content.should.eql(['1\n\n1']);
        slides[1].content.should.eql(['2']);
        slides[2].content.should.eql(['3']);
      });
  
      it('should ignore blank lines when calculating whitespace to trim', function () {
        var slides = parser.parse('      1\n \n      1\n      ---\n      2\n      ---\n      3');
  
        slides[0].content.should.eql(['1\n\n1']);
        slides[1].content.should.eql(['2']);
        slides[2].content.should.eql(['3']);
      });
  
      it('should preserve leading whitespace that goes beyond the minimum whitespace on inner lines', function () {
        var slides = parser.parse('      1\n      ---\n          2\n      ---\n      3');
  
        slides[0].content.should.eql(['1']);
        slides[1].content.should.eql(['    2\n']); // Note: lexer includes trailing newines in code blocks
        slides[2].content.should.eql(['3']);
      });
  
      it('should preserve leading whitespace that goes beyond the minimum whitespace on the first line', function () {
        var slides = parser.parse('          1\n      ---\n      2\n      ---\n      3');
  
        slides[0].content.should.eql(['    1\n']); // Note: lexer includes trailing newines in code blocks
        slides[1].content.should.eql(['2']);
        slides[2].content.should.eql(['3']);
      });
  
      it('should preserve leading whitespace that goes beyond the minimum whitespace on the last line', function () {
        var slides = parser.parse('      1\n      ---\n      2\n      ---\n          3');
  
        slides[0].content.should.eql(['1']);
        slides[1].content.should.eql(['2']);
        slides[2].content.should.eql(['    3']);
      });
    });
  
    var parser;
  
    beforeEach(function () {
      parser = new Parser();
    });
  
  });
  