styledocco
Advanced tools
Comparing version 0.1.1 to 0.2.0
258
lib/main.js
(function() { | ||
var Language, buildRootPath, cssPath, exec, file, files, findit, fs, generateIndex, generateSourceHtml, getLanguage, input, jade, key, languages, link, makeDestination, makeSections, marked, menu, mkdirp, optimist, options, outputDir, overwriteResources, parts, path, preProcess, renderTemplate, sources, templateDir, trimNewLines, writeFile, _i, _len; | ||
var buildRootPath, cssPath, currentDir, file, files, findFile, findit, fs, generateSourceHtml, getSections, input, jade, key, langs, link, makeDestination, menu, mkdirp, optimist, options, outputDir, overwriteResources, parser, parts, path, preProcess, readme, renderTemplate, sections, sources, templateDir, writeFile, _, _i, _len; | ||
exec = require('child_process').exec; | ||
fs = require('fs'); | ||
@@ -10,4 +8,2 @@ | ||
marked = require('marked'); | ||
mkdirp = require('mkdirp'); | ||
@@ -21,2 +17,8 @@ | ||
langs = require('./languages'); | ||
parser = require('./parser'); | ||
_ = require('./utils'); | ||
options = optimist.usage('Usage: $0 [options] [INPUT]').describe('name', 'Name of the project').alias('n', 'name').demand('name').describe('out', 'Output directory').alias('o', 'out')["default"]('out', 'docs').describe('tmpl', 'Template directory').boolean('overwrite').describe('overwrite', 'Overwrite existing files in target dir').argv; | ||
@@ -26,2 +28,4 @@ | ||
currentDir = "" + (process.cwd()) + "/"; | ||
outputDir = options.out; | ||
@@ -33,101 +37,20 @@ | ||
marked.setOptions({ | ||
sanitize: false | ||
}); | ||
Language = (function() { | ||
function Language(symbols, preprocessor) { | ||
this.symbols = symbols; | ||
this.preprocessor = preprocessor; | ||
this.regexs = {}; | ||
if (this.symbols.single) { | ||
this.regexs.single = new RegExp('^\\s*' + this.symbols.single); | ||
} | ||
this.regexs.multi_start = new RegExp(/^[\s]*\/\*/); | ||
this.regexs.multi_end = new RegExp(/\*\//); | ||
getSections = function(filename) { | ||
var blocks, data, lang, sections; | ||
data = fs.readFileSync(filename, "utf-8"); | ||
lang = langs.getLanguage(filename); | ||
if (lang != null) { | ||
blocks = parser.extractBlocks(lang, data); | ||
sections = parser.makeSections(blocks); | ||
} else { | ||
sections = parser.makeSections([ | ||
{ | ||
docs: data, | ||
code: '' | ||
} | ||
]); | ||
} | ||
Language.prototype.checkType = function(str) { | ||
if (str.match(this.regexs.multi_start) && str.match(this.regexs.multi_end)) { | ||
return 'single'; | ||
} else if (str.match(this.regexs.multi_start)) { | ||
return 'multistart'; | ||
} else if (str.match(this.regexs.multi_end)) { | ||
return 'multiend'; | ||
} else if ((this.regexs.single != null) && str.match(this.regexs.single)) { | ||
return 'single'; | ||
} else { | ||
return 'code'; | ||
} | ||
}; | ||
Language.prototype.filter = function(str) { | ||
var n, re, _ref; | ||
_ref = this.regexs; | ||
for (n in _ref) { | ||
re = _ref[n]; | ||
str = str.replace(re, ''); | ||
} | ||
return str; | ||
}; | ||
Language.prototype.compile = function(filename, cb) { | ||
if (this.preprocessor != null) { | ||
return exec("" + this.preprocessor.cmd + " " + (this.preprocessor.args.join(' ')) + " " + filename, function(err, stdout, stderr) { | ||
return cb(err, stdout); | ||
}); | ||
} else { | ||
return fs.readFile(filename, 'utf-8', function(err, data) { | ||
return cb(err, data); | ||
}); | ||
} | ||
}; | ||
return Language; | ||
})(); | ||
languages = { | ||
'.css': new Language({ | ||
multi: ["/*", "*/"] | ||
}), | ||
'.scss': new Language({ | ||
single: '//', | ||
multi: ["/*", "*/"] | ||
}, { | ||
cmd: 'scss', | ||
args: ['-t', 'compressed'] | ||
}), | ||
'.sass': new Language({ | ||
single: '//', | ||
multi: ["/*", "*/"] | ||
}, { | ||
cmd: 'sass', | ||
args: ['-t', 'compressed'] | ||
}), | ||
'.less': new Language({ | ||
single: '//', | ||
multi: ["/*", "*/"] | ||
}, { | ||
cmd: 'lessc', | ||
args: ['-x'] | ||
}), | ||
'.styl': new Language({ | ||
single: '//', | ||
multi: ["/*", "*/"] | ||
}, { | ||
cmd: 'stylus', | ||
args: ['-c', '<'] | ||
}) | ||
return sections; | ||
}; | ||
getLanguage = function(source) { | ||
return languages[path.extname(source)]; | ||
}; | ||
trimNewLines = function(str) { | ||
return str.replace(/^\n*/, '').replace(/\n*$/, ''); | ||
}; | ||
makeDestination = function(file) { | ||
@@ -150,39 +73,6 @@ return path.join(path.dirname(file), path.basename(file, path.extname(file)) + '.html'); | ||
var lang; | ||
lang = getLanguage(filename); | ||
lang = langs.getLanguage(filename); | ||
return lang.compile(filename, cb); | ||
}; | ||
makeSections = function(lang, data) { | ||
var code, docs, formatCode, formatDocs, line, lines, sections; | ||
lines = data.split('\n'); | ||
sections = []; | ||
formatDocs = function(line) { | ||
return "" + (lang.filter(line)) + "\n"; | ||
}; | ||
formatCode = function(line) { | ||
return "" + line + "\n"; | ||
}; | ||
while (lines.length) { | ||
docs = code = ''; | ||
while (lines.length && lang.checkType(lines[lines.length - 1]) === 'code') { | ||
code = formatCode(lines.pop()) + code; | ||
} | ||
while (lines.length && lang.checkType(lines[lines.length - 1]) === 'single') { | ||
docs = formatDocs(lines.pop()) + docs; | ||
} | ||
if (lines.length && lang.checkType(lines[lines.length - 1]) === 'multiend') { | ||
while (lines.length) { | ||
line = lines.pop(); | ||
docs = formatDocs(line) + docs; | ||
if (lang.checkType(line) === 'multistart') break; | ||
} | ||
} | ||
sections.push({ | ||
docs: marked(docs.trim()), | ||
code: trimNewLines(code) | ||
}); | ||
} | ||
return sections.reverse(); | ||
}; | ||
renderTemplate = function(templateName, content) { | ||
@@ -197,53 +87,26 @@ var template, templateFile; | ||
generateSourceHtml = function(source, menu, sections) { | ||
var dest; | ||
dest = makeDestination(source); | ||
return preProcess(source, function(err, css) { | ||
var data, html; | ||
if (err != null) throw err; | ||
data = { | ||
title: "" + options.name + " – " + source, | ||
project: { | ||
name: options.name, | ||
menu: menu, | ||
root: buildRootPath(source) | ||
}, | ||
sections: sections, | ||
css: css | ||
}; | ||
generateSourceHtml = function(source, data) { | ||
var dest, render; | ||
dest = makeDestination(source.replace(/readme/i, 'index')); | ||
data.project = { | ||
name: options.name, | ||
menu: menu, | ||
root: buildRootPath(source.replace(/readme/i, 'index')) | ||
}; | ||
render = function(data) { | ||
var html; | ||
html = renderTemplate('docs', data); | ||
console.log("styledocco: " + source + " -> " + (path.join(outputDir, dest))); | ||
return writeFile(dest, html); | ||
}); | ||
}; | ||
generateIndex = function(menu) { | ||
var content, currentDir, data, dest, files, html, readme; | ||
currentDir = "" + (process.cwd()) + "/"; | ||
dest = "index.html"; | ||
if (fs.statSync(input).isDirectory()) { | ||
files = fs.readdirSync(input).filter(function(file) { | ||
return file.toLowerCase().match(/^readme/); | ||
}; | ||
if (langs.isSupported(source)) { | ||
return preProcess(source, function(err, css) { | ||
if (err != null) throw err; | ||
data.css = css; | ||
return render(data); | ||
}); | ||
if (files[0] != null) readme = path.join(input, files[0]); | ||
} else { | ||
data.css = ''; | ||
return render(data); | ||
} | ||
if (readme == null) { | ||
files = fs.readdirSync(currentDir).filter(function(file) { | ||
return file.toLowerCase().match(/^readme/); | ||
}); | ||
if (files[0] != null) readme = path.join(currentDir, files[0]); | ||
} | ||
content = readme != null ? marked(fs.readFileSync(readme, 'utf-8')) : "<h1>Readme</h1><p>Please add a README file to this project.</p>"; | ||
data = { | ||
title: options.name, | ||
project: { | ||
name: options.name, | ||
menu: menu, | ||
root: './' | ||
}, | ||
content: content | ||
}; | ||
html = renderTemplate('index', data); | ||
console.log("styledocco: " + (files[0] || './') + " -> " + (path.join(outputDir, dest))); | ||
return writeFile(dest, html); | ||
}; | ||
@@ -263,3 +126,4 @@ | ||
if (source.match(/(\/|^)\./)) return false; | ||
if (!(path.extname(source) in languages)) return false; | ||
if (source.match(/(\/|^)_.*\.s[ac]ss$/)) return false; | ||
if (!langs.isSupported(source)) return false; | ||
if (!fs.statSync(source).isFile()) return false; | ||
@@ -286,9 +150,29 @@ return true; | ||
generateIndex(menu); | ||
findFile = function(dir, re) { | ||
var _ref; | ||
if (!fs.statSync(dir).isDirectory()) return null; | ||
return (_ref = fs.readdirSync(dir).filter(function(file) { | ||
return file.match(re); | ||
})) != null ? _ref[0] : void 0; | ||
}; | ||
readme = findFile(input, /^readme/i) || findFile(currentDir, /^readme/i) || findFile(templateDir, /^readme/i); | ||
sections = getSections(readme); | ||
generateSourceHtml(readme, { | ||
menu: menu, | ||
sections: sections, | ||
title: '', | ||
description: '' | ||
}); | ||
files.forEach(function(file) { | ||
var code, sections; | ||
code = fs.readFileSync(file, "utf-8"); | ||
sections = makeSections(getLanguage(file), code); | ||
return generateSourceHtml(file, menu, sections); | ||
sections = getSections(file); | ||
return generateSourceHtml(file, { | ||
menu: menu, | ||
sections: sections, | ||
title: '', | ||
description: '' | ||
}); | ||
}); | ||
@@ -295,0 +179,0 @@ |
@@ -10,3 +10,3 @@ { | ||
"author": "Jacob Rask <jacob@jacobrask.net>", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"licenses": [ | ||
@@ -41,3 +41,4 @@ { | ||
"devDependencies": { | ||
"coffee-script": "1.2.x" | ||
"coffee-script": "1.2.x", | ||
"nodeunit": "0.7.4" | ||
}, | ||
@@ -44,0 +45,0 @@ "directories": { |
@@ -1,15 +0,14 @@ | ||
_______ __ __ _____ | ||
| __| |_.--.--| |-----.| \-----.----.----.-----. | ||
|__ | _| | | | -__|| -- | _ | __| __| _ | | ||
|_______|____|___ |__|_____||_____/_____|____|____|_____| | ||
|_____| | ||
<pre> _______ __ __ _____ | ||
| __| |_.--.--| |-----.| \-----.----.----.-----. | ||
|__ | _| | | | -__|| -- | _ | __| __| _ | | ||
|_______|____|___ |__|_____||_____/_____|____|____|_____| | ||
|_____|</pre> | ||
## About | ||
StyleDocco generates documentation and style guide documents from your stylesheets. | ||
It takes the comments from stylesheets and produces HTML documents that display your comments alongside your code, with any HTML snippets from the comments rendered using the processed stylesheets. | ||
Stylesheet comments will be parsed through [Markdown](http://daringfireball.net/projects/markdown/syntax) and displayed in a generated HTML document. You can write code examples inside [GitHub Markdown](http://github.github.com/github-flavored-markdown/) code fences (<code>```</code>) or prefixed with 4 spacesin your comments, and StyleDocco both renders the HTML and shows the code example. | ||
There is no special syntax, comments are just parsed with (GitHub flavored) Markdown. This means that the documentation will still make sense when reading the plain stylesheets, or if you decide to not keep using StyleDocco. | ||
The document automatically starts a new section when it encounters a level 1 or 2 heading. Read more about the syntax in the [Markdown guide](http://daringfireball.net/projects/markdown/syntax). Only comments at the beginning of new lines are included, so to exclude something from the style guide, put some whitespace before the comment. | ||
@@ -21,3 +20,3 @@ If your project includes a `README` file, it will be used as the base for an `index.html`. StyleDocco will also add some default styles to your documentation, but they are easy to modify to make it fit with your project. | ||
## Install | ||
## Installation | ||
@@ -28,5 +27,5 @@ StyleDocco requires [Node.js](http://nodejs.org). | ||
or checkout this repository. | ||
or clone the [GitHub repository](https://github.com/jacobrask/styledocco). | ||
StyleDocco is free software, released under the MIT license. | ||
StyleDocco is free software, released under the [MIT license](https://raw.github.com/jacobrask/styledocco/master/LICENSE). | ||
@@ -48,12 +47,7 @@ | ||
/* <button class="btn primary">Primary</button> | ||
Provides extra visual weight and identifies the primary action in a set of buttons */ | ||
.btn.primary { | ||
background: blue; | ||
color: white; | ||
} | ||
<button class="btn primary">Primary</button> | ||
Would output an HTML document with one column displaying the rendered button followed by the description, and another column with the code. The code will also be included in a `style` element of the document. | ||
This page is an example itself, as it was generated from the StyleDocco readme file. The [docs](resources/docs.html) file is the documentation of the default StyleDocco CSS file. | ||
See the `examples` folder for more in-depth examples. | ||
An additional example was generated from a modified file of the [Twitter Bootstrap](examples/bootstrap/docs/less/buttons.html) project. | ||
@@ -63,5 +57,4 @@ | ||
Thanks to: | ||
A lot of the heavy lifting in StyleDocco is done by the excellent [Marked](https://github.com/chjj/marked) module by Christopher Jeffrey. The original [Docco](https://github.com/jashkenas/docco) by Jeremy Ashkenas and [Docco Husky](https://github.com/mbrevoort/docco-husky) by Mike Brevoort were also of great help to this project. | ||
* [jashkenas](https://github.com/jashkenas/docco) | ||
* [mbrevoort](https://github.com/mbrevoort/docco-husky) | ||
<a href="https://github.com/jacobrask/styledocco" id="styledocco-fork-me"><img style="position:fixed;top:0;right:0;border:0;" src="https://a248.e.akamai.net/assets.github.com/img/7afbc8b248c68eb468279e8c17986ad46549fb71/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub"></a> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
384847
38
1795
2
57
3
2