diff --git a/lib/app/js/directives/section.js b/lib/app/js/directives/section.js index 873a59c4..1db85e8a 100644 --- a/lib/app/js/directives/section.js +++ b/lib/app/js/directives/section.js @@ -8,8 +8,10 @@ angular.module('sgApp') templateUrl: 'views/partials/section.html', link: function(scope, element, attrs) { - //init setting based on global 'showAllMarkup' value + // Init setting based on global 'showAllMarkup' value scope.section.showMarkup = scope.markup.isVisible; + // By default do not show CSS markup + scope.section.showCSS = false; scope.showSingleMarkupBox = function(index) { if (!scope.section.showMarkup) { @@ -22,6 +24,18 @@ angular.module('sgApp') scope.section.showMarkup = false; } } + + scope.showSingleCSSBox = function(index) { + if (!scope.section.showCSS) { + scope.section.showCSS = true; + } + } + + scope.hideSingleCSSBox = function(index) { + if (scope.section.showCSS) { + scope.section.showCSS = false; + } + } } }; }]); diff --git a/lib/app/sass/app.scss b/lib/app/sass/app.scss index 82a81919..f840b07c 100644 --- a/lib/app/sass/app.scss +++ b/lib/app/sass/app.scss @@ -692,6 +692,11 @@ $mobile: new-breakpoint(max-width 480px); padding: 1em; } + .hljs { + max-height: 400px; + overflow-y: auto; + } + a.show-section { display: block; cursor: pointer; diff --git a/lib/app/views/partials/section.html b/lib/app/views/partials/section.html index 3077bd5e..4859b2be 100644 --- a/lib/app/views/partials/section.html +++ b/lib/app/views/partials/section.html @@ -43,14 +43,27 @@

+ +
+
+ + + +
+
+        
+      
+ Show CSS +
+
-
+ -
-        
+      
+        
       
Show markup
diff --git a/lib/modules/kss.js b/lib/modules/kss.js index 08296f38..b7368fb0 100644 --- a/lib/modules/kss.js +++ b/lib/modules/kss.js @@ -1,8 +1,9 @@ 'use strict'; var kss = require('kss'), - sanitizeHtml = require('sanitize-html'), - wrapperMarkup = require('./wrapper-markup'); + Q = require('q'), + kssSplitter = require('./kss-splitter'), + sanitizeHtml = require('sanitize-html'); // Parses kss.KssSection to JSON function jsonSections(sections) { @@ -32,30 +33,84 @@ function jsonModifiers(modifiers) { }); } +function trimLinebreaks(str) { + // Remove leading and trailing whitespaces + if (!str) { + return str; + } + return str.replace(/^[\r\n]+|[\r\n]+$/g, ''); +} + function sanitize(string) { return sanitizeHtml(string, {allowedTags: [], allowedAttributes: []}); } -module.exports = { +function processBlock(block, options, json) { + var blockPromise = Q.defer(); - // Parse node-kss object ( {'file.path': 'file.contents.toString('utf8'}' ) - parseKSS: function(files, options, success) { - var json = {}; - kss.parse(files, options, function(err, styleguide) { + kss.parse(block.kss, options, function(err, styleguide) { + var section, + blockStyles; if (err) { new PluginError(PLUGIN_NAME, 'Error parsing', err); + blockPromise.resolve(); return false; } else { - json.sections = jsonSections(styleguide.section()); + section = jsonSections(styleguide.section()); - /* Make inherited wrappers */ - json.sections = wrapperMarkup.generateSectionWrapperMarkup(json.sections); + if (section.length > 0) { + if (section.length > 1) { + console.warn('Warning: KSS splitter returned more than 1 KSS block. Styleguide might not be properly generated.'); + } + blockStyles = trimLinebreaks(block.code); - if (typeof success === 'function') { - success(json); + // Add related CSS to section + if (blockStyles && blockStyles !== '') { + section[0].css = blockStyles; + } + json.sections = json.sections.concat(section); } + blockPromise.resolve(); } }); + return blockPromise; } +function processFile(contents, options, json) { + var filePromise = Q.defer(), + blockPromises = [], + splittedFile = kssSplitter.getBlocks(contents); + + // Process every block in the current file + splittedFile.forEach(function(block) { + blockPromises.push(processBlock(block, options, json)); + }); + + Q.all(blockPromises).then(function() { + // All blocks are processed, resolve file promise + filePromise.resolve(); + }); + + return filePromise; +} + +module.exports = { + // Parse node-kss object ( {'file.path': 'file.contents.toString('utf8'}' ) + parseKSS: function(files, options, success) { + var json = { + sections: [] + }, + filePromises = [], + fileKeys = Object.keys(files); + + fileKeys.forEach(function(filePath) { + var contents = files[filePath]; + filePromises.push(processFile(contents, options, json)); + }); + + Q.all(filePromises).then(function() { + // All files are processed. Call success callback + success(json); + }); + } } diff --git a/lib/styleguide.js b/lib/styleguide.js index c20df44f..891bb830 100644 --- a/lib/styleguide.js +++ b/lib/styleguide.js @@ -22,6 +22,7 @@ var through = require('through2'), parseKSS = require(__dirname + '/modules/kss').parseKSS, pseudoSelectors = require(__dirname + '/modules/pseudo-selectors'), preprocess = require(__dirname + '/modules/preprocess'), + wrapperMarkup = require(__dirname + '/modules/wrapper-markup'), path = require('path'), sgServer = require(__dirname + '/server'), File = require('vinyl'), @@ -99,6 +100,7 @@ module.exports = function(opt) { // After reading all files, parse them and generate data for styleguide function(callback) { var _this = this; + parseKSS(filesBuffer, opt.kssOpt, function(styleguide) { var pushAllFiles = function() { return through.obj(function(file, enc, cb) { @@ -109,6 +111,9 @@ module.exports = function(opt) { }) }; + // Make inherited wrappers + styleguide.sections = wrapperMarkup.generateSectionWrapperMarkup(styleguide.sections); + // Store settings inside the styleguide JSON styleguide.config = opt; diff --git a/package.json b/package.json index 8f4b4f74..45618907 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "node-neat": "^1.3.0", "node.extend": "^1.1.2", "ometajs": "^3.3.7", + "q": "^1.1.1", "run-sequence": "^1.0.1", "sanitize-html": "^1.4.3", "serve-favicon": "^2.1.6", diff --git a/test/data/wrapper.scss b/test/data/wrapper.scss deleted file mode 100644 index 15d1c2fd..00000000 --- a/test/data/wrapper.scss +++ /dev/null @@ -1,56 +0,0 @@ -// Section 1 -// -// markup: -// -// -// Styleguide 1.0 - -// Side nav item -// -// markup: -//

Content inside outer wrapper

-// -// -// -// -// -// -// Styleguide 1.1 - -.test { -} - -// Child section -// -// markup: -//

Content inside outer wrapper

-// -// Styleguide 1.1.1 - -.test2 { -} - -// Parent section -// -// markup: -//

Content inside inner and outer wrapper

-// -// -// -// -// -// -// Styleguide 1.1.2 - -.test3 { -} - -// Child section -// -// markup: -//

Second level content

-// -// Styleguide 1.1.2.1 - -.test4 { -} \ No newline at end of file diff --git a/test/kss-parser.js b/test/kss-parser.js deleted file mode 100644 index 02506eff..00000000 --- a/test/kss-parser.js +++ /dev/null @@ -1,52 +0,0 @@ -var gulp = require('gulp'), - chai = require('chai'), - expect = chai.expect, - fs = require('fs'), - parseKSS = require('../lib/modules/kss').parseKSS; - -describe('KSS parser', function() { - - var json = {}, - removeLinebreaks = function(text) { - return text.replace(/(\r\n|\n|\r)/gm, ''); - } - - before(function(done) { - filesBuffer = { - './test/data/wrapper.scss': fs.readFileSync('./test/data/wrapper.scss', 'utf-8') - }; - parseKSS( - filesBuffer, - { markdown: true, multiline: true, typos: false }, - function(data) { - json = data; - done(); - } - ); - }); - - it('should not add wrapper to the parent sections', function() { - var wrappedMarkup = ''; - expect(removeLinebreaks(json.sections[0].wrappedMarkup)).eql(wrappedMarkup); - }); - - it('should add wrapper markup to the current section', function() { - var wrappedMarkup = '

Content inside outer wrapper

'; - expect(removeLinebreaks(json.sections[1].wrappedMarkup)).eql(wrappedMarkup); - }); - - it('should inherit wrapper markup to the subsection', function() { - var wrappedMarkup = '

Content inside outer wrapper

'; - expect(removeLinebreaks(json.sections[2].wrappedMarkup)).eql(wrappedMarkup); - }); - - it('should inherit wrapper markup to the subsection with the current wrapper markup', function() { - var wrappedMarkup = '

Content inside inner and outer wrapper

'; - expect(removeLinebreaks(json.sections[3].wrappedMarkup)).eql(wrappedMarkup); - }); - - it('should inherit all parent wrapper markups to the sub-sub-section', function() { - var wrappedMarkup = '

Second level content

'; - expect(removeLinebreaks(json.sections[4].wrappedMarkup)).eql(wrappedMarkup); - }); -}); diff --git a/test/projects/less-project/source/styles/style.less b/test/projects/less-project/source/styles/style.less index beb884d4..2d7af3d0 100644 --- a/test/projects/less-project/source/styles/style.less +++ b/test/projects/less-project/source/styles/style.less @@ -1,68 +1,30 @@ @import "_styleguide_variables"; -// Colors -// -// This section demonstrates how to present your color variables using -// styleguide -// -// $color-red - Red test color -// $color-green - Green test color -// $color-blue - Blue test color +// First section // // Markup: -//
+//
Section markup
// // Styleguide 1.0 -// Typography +.section { + background-color: @color-red; + color: @color-green; +} + +// Section with modifiers // -// You can also use styleguide to demonstrate your typographic scale etc. +// $color-red - Red test color +// $color-green - Green test color +// $color-blue - Blue test color // // Markup: -//
-//

Quick brown fox

-//

Quick brown fox

-//

Quick brown fox

-//

Quick brown fox

-//

Quick brown fox

-// Quick brown fox -//
+//
// // Styleguide 2.0 -// Elements -// -// This section contains example documentation of different kinds of html -// elements +// Section without markup // // Styleguide 3.0 -// Buttons -// -// This section demonstrates the use of modifiers -// -// default - This is the default state of a button element -// .green - This is a button with a class modifier -// .red - This is another button with a class modifier -// :hover - This is a button with the hover pseudo modifier -// -// Markup: -// -// -// Styleguide 3.1 - -.button { - border: 1px solid black; - padding: 1em; - border-radius: 5px; - - &.green { - background: @color-green; - } - &.red { - background: @color-red; - } - &:hover { - background: yellow; - } -} +.test-css {color: purple;} \ No newline at end of file diff --git a/test/projects/scss-project/source/styles/style.scss b/test/projects/scss-project/source/styles/style.scss index 512701e3..110fe4cb 100644 --- a/test/projects/scss-project/source/styles/style.scss +++ b/test/projects/scss-project/source/styles/style.scss @@ -1,147 +1,30 @@ @import "styleguide_variables"; -// Colors -// -// This section demonstrates how to present your color variables using -// styleguide -// -// $color-red - Red test color -// $color-green - Green test color -// $color-blue - Blue test color +// First section // // Markup: -//
+//
Section markup
// // Styleguide 1.0 -// Typography -// -// You can also use styleguide to demonstrate your typographic scale etc. -// -// Markup: -//
-//

Quick brown fox

-//

Quick brown fox

-//

Quick brown fox

-//

Quick brown fox

-//

Quick brown fox

-// Quick brown fox -//
-// -// Styleguide 2.0 - -html {font-size: 1em;} - -body { - background-color: white; - font-family: 'Libre Baskerville', serif; - font-weight: 400; - line-height: 1.45; - color: #333; +.section { + background-color: $color-red; + color: $color-green; } -p {margin-bottom: 1.3em;} - -h1, h2, h3, h4 { - margin: 1.414em 0 0.5em; - font-weight: inherit; - line-height: 1.2; -} - -h1 { - margin-top: 0; - font-size: 3.998em; -} - -h2 {font-size: 2.827em;} - -h3 {font-size: 1.999em;} - -h4 {font-size: 1.414em;} - -small, .font_small {font-size: 0.707em;} - -// Elements +// Section with modifiers // -// This section contains example documentation of different kinds of html -// elements -// -// Styleguide 3.0 - -// Buttons -// -// This section demonstrates the use of modifiers -// -// default - This is the default state of a button element -// .green - This is a button with a class modifier -// .red - This is another button with a class modifier -// :hover - This is a button with the hover pseudo modifier +// $color-red - Red test color +// $color-green - Green test color +// $color-blue - Blue test color // // Markup: -// +//
// -// Styleguide 3.1 - -.button { - border: 1px solid black; - padding: 1em; - border-radius: 5px; - - &.green { - background: $color-green; - } - &.red { - background: $color-red; - } - &:hover { - background: yellow; - } -} +// Styleguide 2.0 -// Grid -// -// You can use styleguide visualize your page layouts +// Section without markup // -// Markup: -//
-//
-//
-//
-//
-//
-//
-//
-// -// Styleguide 3.2 - -.grid-wrapper { - box-sizing: border-box; - * { - display: inline-block; - } - - .columns { - float: left; - box-sizing: border-box; - &.twelve { - width: 100%; - } - - &.six { - width: 50%; - } - - &.four { - width: 33.33%; - } - } -} +// Styleguide 3.0 -// Components -// -// You can view your Angular Directives implemented for the project -// -// markup: -//
-// -// Styleguide 4.0 +.test-css {color: purple;} \ No newline at end of file diff --git a/test/structure.js b/test/structure.js index 7e39fc6c..c8ec98cb 100644 --- a/test/structure.js +++ b/test/structure.js @@ -235,11 +235,23 @@ describe('overview.html', function() { }); it('should print markup if defined', function() { - expect(jsonData.sections[1].markup).to.not.be.empty; + expect(jsonData.sections[0].markup).to.not.be.empty; }); it('should not print empty markup', function() { expect(jsonData.sections[2].markup).to.not.exist; }); + + it('should have all the modifiers', function() { + expect(jsonData.sections[1].modifiers.length).to.eql(3) + }); + + it('should have section CSS', function() { + expect(jsonData.sections[2].css).to.eql('.test-css {color: purple;}'); + }); + + it('should not print empty markup', function() { + expect(jsonData.sections[1].css).to.not.exist; + }); }); }); diff --git a/test/wrapper-markup.js b/test/wrapper-markup.js new file mode 100644 index 00000000..0c5a9c64 --- /dev/null +++ b/test/wrapper-markup.js @@ -0,0 +1,113 @@ +var gulp = require('gulp'), + chai = require('chai'), + expect = chai.expect, + fs = require('fs'), + multiline = require('multiline'), + wrapperMarkup = require('../lib/modules/wrapper-markup'); + +describe('KSS wrapper markup generator', function() { + + var json = {}, + removeLinebreaks = function(text) { + return text.replace(/(\r\n|\n|\r)/gm, ''); + } + + beforeEach(function() { + var markup = []; + markup[0] = multiline(function() { +/* + +*/ + }), + markup[1] = multiline(function() { +/* +

Content inside outer wrapper

+ + + + + +*/ + }), + markup[2] = multiline(function() { +/* +

Content inside outer wrapper

+*/ + }), + markup[3] = multiline(function() { +/* +

Content inside inner and outer wrapper

+ + + + + +*/ + }), + markup[4] = multiline(function() { +/* +

Second level content

+*/ + }); + + json = { + sections: [{ + header: 'Main section', + description: '', + reference: '1.0', + modifiers: [], + markup: markup[0] + }, { + header: 'Define outer wrapper', + description: '', + reference: '1.1', + modifiers: [], + markup: markup[1] + }, { + header: 'Content inside outer wrapper', + description: '', + reference: '1.1.1', + modifiers: [], + markup: markup[2] + }, { + header: 'Content inside inner and outer wrapper', + description: '', + reference: '1.1.2', + modifiers: [], + markup: markup[3] + }, { + header: 'Multiple inherited wrapper', + description: '', + reference: '1.1.2.1', + modifiers: [], + markup: markup[4] + }] + } + json.sections = wrapperMarkup.generateSectionWrapperMarkup(json.sections); + }); + + it('should not add wrapper to the parent sections', function() { + var wrappedMarkup = ''; + expect(removeLinebreaks(json.sections[0].wrappedMarkup)).eql(wrappedMarkup); + }); + + it('should add wrapper markup to the current section', function() { + var wrappedMarkup = '

Content inside outer wrapper

'; + expect(removeLinebreaks(json.sections[1].wrappedMarkup)).eql(wrappedMarkup); + }); + + it('should inherit wrapper markup to the subsection', function() { + var wrappedMarkup = '

Content inside outer wrapper

'; + expect(removeLinebreaks(json.sections[2].wrappedMarkup)).eql(wrappedMarkup); + }); + + it('should inherit wrapper markup to the subsection with the current wrapper markup', function() { + var wrappedMarkup = '

Content inside inner and outer wrapper

'; + expect(removeLinebreaks(json.sections[3].wrappedMarkup)).eql(wrappedMarkup); + }); + + it('should inherit all parent wrapper markups to the sub-sub-section', function() { + var wrappedMarkup = '

Second level content

'; + expect(removeLinebreaks(json.sections[4].wrappedMarkup)).eql(wrappedMarkup); + }); +});