Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
316 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
# IDE | ||
*.idea | ||
*.iml | ||
|
||
# Logs | ||
logs | ||
*.log | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,121 @@ | ||
# sourcejs-contrib-dss | ||
CSS Documentation parser integration for transporting DSS into SourceJS Specs. | ||
# CSS Documentation support for SourceJS | ||
|
||
Appends rendered [DSS](https://github.com/darcyclarke/DSS) documentation into SourceJS Spec pages. | ||
|
||
[SourceJS](http://sourcejs.com) plugin (for 0.5.0+ version). | ||
|
||
## Install | ||
|
||
To install middleware, run npm command in `sourcejs/user` folder: | ||
|
||
``` | ||
npm install sourcejs-contrib-dss --save | ||
``` | ||
|
||
After restarting your app, middleware will be loaded automatically. To disable it, remove npm module and restart the app. | ||
|
||
## Usage | ||
|
||
DSS works as SourceJS middleware, when Spec (documentation page) is requested, plugin is searching CSS files in Spec folder by defined mask. | ||
|
||
All found CSS (or LESS/SASS/SCSS/Stylus) will be processed through [DSS](https://github.com/darcyclarke/DSS) in runtime, during request. | ||
|
||
Here's an example of Spec folder structure | ||
|
||
``` | ||
specs/button | ||
button.css | ||
readme.md | ||
info.json | ||
``` | ||
|
||
`button.css` contents: | ||
|
||
```css | ||
/** | ||
* @name Default | ||
* | ||
* @state .button-pro_big - Bigger version | ||
* | ||
* @markup | ||
* <button class="button-pro">Click me</button> | ||
*/ | ||
|
||
.button-pro {} | ||
.button-pro.button-pro_big {} | ||
|
||
/** | ||
* @name Disabled | ||
* | ||
* @state .button-pro_big - Bigger disabled version | ||
* | ||
* @markup | ||
* <button class="button-pro button-pro_disabled">Click me</button> | ||
*/ | ||
|
||
.button-pro.button-pro_disabled {} | ||
``` | ||
|
||
Spec rendered result (http://127.0.0.1:8080/specs/button): | ||
|
||
![image](http://d.pr/i/GH6g+) | ||
|
||
`readme.md` contents will be rendered at the top of Spec file. Other file types as `index.src` or `index.jade` (with [Jade plugin](https://github.com/sourcejs/sourcejs-jade)) could also be used. | ||
|
||
**Note** that Spec file and `info.json` should be present in folder for page to load. | ||
|
||
## Options | ||
|
||
You can configure plugin options from `user/options.js`: | ||
|
||
```js | ||
{ | ||
core: {}, | ||
assets: {}, | ||
plugins: { | ||
dss: { | ||
targetCssMask: '**/*.{css,less,stylus,sass,scss}', | ||
visibleCode: true, | ||
templates: { | ||
sections: path.join(__dirname, '../views/sections.ejs') | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### targetCssMask | ||
|
||
Type: `String` | ||
Default value: `**/*.{css,less,stylus,sass,scss}` | ||
|
||
Glob mask for searching CSS files for DSS parsing, starting from requested Spec path (https://github.com/isaacs/node-glob). | ||
|
||
### visibleCode | ||
|
||
Type: `Boolean` | ||
Default: `true` | ||
|
||
Set `source_visible` to every `src-html` code containers to show code preview by default. Set to `false` if you prefer hiding code blocks by default (toggled from menu `Show source code`). | ||
|
||
### templates | ||
|
||
Type: `Object` | ||
|
||
#### templates.item | ||
|
||
Type: `String` | ||
Default: `path.join(__dirname, '../views/sections.ejs')` | ||
|
||
Set path to EJS template for rendering DSS JSON result. Currently this plugin uses only one template for sections. | ||
|
||
## Upcoming features | ||
|
||
* DSS parser caching | ||
* Pre-build cache (during app start) | ||
* DSS improvements | ||
|
||
## Other SourceJS middlewares | ||
|
||
* https://github.com/sourcejs/sourcejs-jade | ||
* https://github.com/sourcejs/sourcejs-smiles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
var dss = require('dss'); | ||
var path = require('path'); | ||
var deepExtend = require('deep-extend'); | ||
var glob = require('glob'); | ||
var fs = require('fs'); | ||
var ejs = require('ejs'); | ||
var prettyHrtime = require('pretty-hrtime'); | ||
var cheerio = require('cheerio'); | ||
var util = require('util'); | ||
|
||
// Module configuration. Public object is exposed to Front-end via options API | ||
var config = { | ||
enabled: true, | ||
|
||
// Glob mask, starting from requested spec path (https://github.com/isaacs/node-glob) | ||
targetCssMask: '**/*.{css,less,stylus,sass,scss}', | ||
|
||
// Define if example HTML is visible by default | ||
visibleCode: true, | ||
templates: { | ||
sections: path.join(__dirname, '../views/sections.ejs') | ||
}, | ||
|
||
public: {} | ||
}; | ||
// Overwriting base options | ||
deepExtend(config, global.opts.plugins.dss); | ||
|
||
/* | ||
* Gets markup and adds custom class to all first level nodes | ||
* | ||
* @param {String} markup - HTML markup string | ||
* @param {String} cssClass - CSS class to add | ||
* */ | ||
var addClassToExample = function(markup, cssClass){ | ||
var $ = cheerio.load('<div id="content">'+ markup +'</div>'); | ||
|
||
// Add to all first level elements a state class | ||
$('#content > *').each(function(){ | ||
$(this).addClass(cssClass); | ||
}); | ||
|
||
return $('#content').html(); | ||
}; | ||
|
||
/* | ||
* Dynamically render DSS into requested Spec | ||
* | ||
* @param {object} req - Request object | ||
* @param {object} res - Response object | ||
* @param {function} next - The callback function | ||
* */ | ||
var processRequest = function (req, res, next) { | ||
if (!config.enabled) { | ||
next(); | ||
return; | ||
} | ||
|
||
if ( | ||
req.specData && | ||
req.specData.info.role !== 'navigation' && // Not navigation page | ||
req.specData.renderedHtml && // Is spec and has renderedHTML in req | ||
!(req.specData.info.plugins && req.specData.info.plugins.dss && !req.specData.info.plugins.dss.enabled) // Is not disabled per Spec | ||
) { | ||
var start = process.hrtime(); | ||
var specPath = path.join(global.app.get('user'), req.path); | ||
var specDirPath = path.dirname(specPath); | ||
|
||
glob(config.targetCssMask, { | ||
cwd: specDirPath | ||
}, function (err, files) { | ||
if (err || files.length === 0) { | ||
next(); | ||
return; | ||
} | ||
|
||
var sectionsTplPath = config.templates.sections; | ||
|
||
fs.readFile(sectionsTplPath, 'utf-8', function(err, file){ | ||
if (err) { | ||
global.log.warn('DSS template not found'+ sectionsTplPath +':', err); | ||
|
||
next(); | ||
return; | ||
} | ||
|
||
var sectionsTemplate = file; | ||
var dataForTemplates = { | ||
config: config, | ||
helpers: { | ||
addClassToExample: addClassToExample | ||
}, | ||
sections: [] | ||
}; | ||
|
||
// Gather all DSS blocks | ||
files.forEach(function(filePath){ | ||
var fullPath = path.join(specDirPath, filePath); | ||
|
||
try { | ||
var file = fs.readFileSync(fullPath, 'utf-8'); | ||
|
||
dss.parse(file, {}, function(parsed) { | ||
|
||
// Normalizing DSS parser output https://github.com/darcyclarke/DSS/issues/58 | ||
parsed.blocks.forEach(function(block){ | ||
for (var key in block) { | ||
var value = block[key]; | ||
|
||
if (key === 'state' && !util.isArray(value)) { | ||
block[key] = [value]; | ||
} | ||
} | ||
}); | ||
|
||
dataForTemplates.sections = dataForTemplates.sections.concat(parsed.blocks); | ||
}); | ||
} catch(err) { | ||
global.log.debug('DSS error parsing '+ fullPath +':', err); | ||
} | ||
}); | ||
|
||
// Update HTML | ||
req.specData.renderedHtml += ejs.render(sectionsTemplate, dataForTemplates); | ||
|
||
var end = process.hrtime(start); | ||
global.log.debug('DSS processing took:', prettyHrtime(end)); | ||
|
||
next(); | ||
}); | ||
|
||
|
||
}); | ||
} else { | ||
next(); | ||
} | ||
}; | ||
|
||
exports.process = processRequest; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<% for (var i = 0; i < sections.length; i++) { %> | ||
<section class="source_section"> | ||
<h2><%= sections[i].name %></h2> | ||
<% if (sections[i].description) { %> | ||
<p><%= sections[i].description %></p> | ||
<% } %> | ||
<% if (sections[i].markup) { %> | ||
<code class="src-html <% if (config.visibleCode) { %>source_visible<% } %>"> | ||
<%- sections[i].markup.escaped %> | ||
</code> | ||
<div class="source_example"> | ||
<%- sections[i].markup.example %> | ||
</div> | ||
<% } %> | ||
<% if (sections[i].state) { %> | ||
<% for (var s = 0; s < sections[i].state.length; s++) { %> | ||
<% var state = sections[i].state[s]; %> | ||
<% var html = helpers.addClassToExample(sections[i].markup.example, state.escaped); %> | ||
<h3><%= state.name %></h3> | ||
<% if (state.description) { %> | ||
<p><%= state.description %></p> | ||
<% } %> | ||
<code class="src-html <% if (config.visibleCode) { %>source_visible<% } %>"> | ||
<%= html %> | ||
</code> | ||
<div class="source_example"> | ||
<%- html %> | ||
</div> | ||
<% } %> | ||
<% } %> | ||
</section> | ||
<% } %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "sourcejs-contrib-dss", | ||
"version": "0.1.0", | ||
"author": "Robert Haritonov", | ||
"description": "CSS Documentation parser integration for transporting DSS into SourceJS Specs", | ||
"dependencies": { | ||
"cheerio": "^0.18.0", | ||
"deep-extend": "^0.3.2", | ||
"dss": "^1.0.4", | ||
"ejs": "^2.3.1", | ||
"glob": "^5.0.3", | ||
"pretty-hrtime": "^1.0.0" | ||
} | ||
} |