winstromming / sassdown Goto Github PK
View Code? Open in Web Editor NEWGenerates styleguides from Markdown comments in CSS, SASS and LESS files using Handlebars
Generates styleguides from Markdown comments in CSS, SASS and LESS files using Handlebars
Found by @sturobson. Added to issues for reference and future fix.
Currently there is no way to include javascript files or external stylesheets (ie icons, fonts) into the output HTML examples.
I know, I know. But it is really cool and I'd love to use sassdown with it.
Is it possible to output how ie. a button would look โ along with the raw html?
My grunt task looks like this:
sassdown: {
options: {
assets: ['.tmp/styles/_.css']
},
files: {
expand: true,
cwd: 'src/styles',
src: ['_.scss'],
dest: '.tmp/styleguide/'
}
}
Copied from pull request #78 in case this isn't the correct fix:
If the files array doesn't resolve anything, sassdown returns Warning: Cannot read property 'orig' of undefined Use --force to continue. Which tells the user very little.
To reproduce, change line 50 in Gruntfile.js to something like cwd: 'test/example/asses/sass/foo' and run grunt sassdown
.
First of all, thanks for this awesome plugin. It's everything I wanted. I have a question and maybe they are already solved but I'll ask anyway
<span class="badge.badge-primary">
<span class="badge.badge-secondary">
<span class="badge.badge-alert">
<span class="badge.badge-info">
<span class="badge.badge-success">
<span class="badge.badge-warning">
Navigation implementation is currently too verbose, which makes modifying template output difficult.
<div id="nav">
<h1><a href="{{> root}}/{{href}}">Styleguide</a></h1>
{{#each pages}}
{{#if isDirectory}}
<h2 class="heading">{{name}}</h2>
<ul class="group">
{{#each pages}}
<li>
{{#if isDirectory}}
<h3 class="heading">{{name}}</h3>
<ul class="group">
{{#each pages}}
<li>
{{#if isDirectory}}
<h4 class="heading">{{name}}</h4>
<ul class="group">
{{#each pages}}
<li>
<a href="{{> root}}/{{href}}">{{title}}</a>
</li>
{{/each}}
</ul>
{{else}}
<a href="{{> root}}/{{href}}">{{title}}</a>
{{/if}}
</li>
{{/each}}
</ul>
{{else}}
<a href="{{> root}}/{{href}}">{{title}}</a>
{{/if}}
</li>
{{/each}}
</ul>
{{else}}
<a href="{{> root}}/{{href}}">{{title}}</a>
{{/if}}
{{/each}}
</div>
Consider reducing necessary code or building an iterative loop that outputs into a single partial, such as {{> navigation}}
, or a group of partials. Look into iteration in native Handlebars or explore pre-compiled options with nodejs.
Currently the Config object is large contains severe duplication/repetition with the File object. See #24.
{
opts: {
readme: false,
theme: 'tasks/data/theme.css',
template: 'tasks/data/template.hbs',
baseUrl: null,
excludeMissing: true,
commentStart: /\/\* (?:[=]{4,}\n[ ]+|(?!\n))/,
commentEnd: /[ ]+[=]{4,} \*\//,
assets: ['test/custom/assets/css/*.css']
},
files: [Object], // full list of all File objects
groups: {
base: {
name: 'base',
pages: [{
heading: 'Base Styles',
group: 'base',
path: 'test/custom/styleguide/base/_base.html',
url: '/test/custom/styleguide/base/_base.html'
}]
},
modules: {
name: 'modules',
pages: [{
heading: 'Media Object',
group: 'modules',
path: 'test/custom/styleguide/modules/_media.html',
url: '/test/custom/styleguide/modules/_media.html'
}]
}
},
module: '/Users/hillsj/Sites/sassdown/tasks/sassdown.js',
template: {
html: [Function],
assets: null
},
root: 'test/custom/assets',
tree: {
name: 'sass',
path: 'test/custom/assets/sass',
type: 'dir',
data: {},
children: [{
name: 'application.sass',
path: 'test/custom/assets/sass/application.sass',
type: 'file',
data: {}
}, {
name: 'base',
path: 'test/custom/assets/sass/base',
type: 'dir',
data: {},
children: [{
name: '_base.sass',
path: 'test/custom/assets/sass/base/_base.sass',
type: 'file',
data: [Object] // contains File object
}]
}, {
name: 'modules',
path: 'test/custom/assets/sass/modules',
type: 'dir',
data: {},
children: [{
name: '_media.sass',
path: 'test/custom/assets/sass/modules/_media.sass',
type: 'file',
data: [Object] // contains File object
}]
}]
}
}
The template.hbs file uses a variable to store the path to the assets folder - the parent folder of the CSS and JavaScript files (see below)
This {{site.assets}}
variable resolves with backslashes rather than forward slashes which causes problems with some browsers on a Windows platform. For example Firefox cannot resolve the file path with a mixture of back and forward slashes - it requires forward slashes to be used.
See screen grab below from the Chrome Dev Tools Inspector for how the above file paths actually resolve.
Hi
just trying out for the first time but getting this error
Warning: Cannot read property 'orig' of undefined Use --force to continue.
Any thoughts?
Cheers
First, this project is amazing!! The last weeks i played with different styleguide tools (grunt-styleguide, kss-node, styledocco). I am so happy that i found this repository.
On my testing trip I found one key feature from kss-node very interesting. Read the part on Multi-line descriptions.
In short - in their markup section they use the {$modifiers}
keyword as a spacer. The next few lines specify the attributes. The syntax is like a list.
This is a example from the kss-node/demo
// Buttons
//
// A majority of buttons in the site are built from the same base class.
//
// Markup:
// <a href="#" class="button {$modifiers}">Link Button</a>
// <button class="button {$modifiers}">Button Element</button>
// <input type="button" class="button {$modifiers}" value="input[type='button']"/>
//
// .primary - Indicate that the button is the primary feature of this form.
// .remove - Indicate that the button will remove a feature, or other negative connotations.
// :hover - Highlight the button when hovered.
// :disabled - Make the button change appearance to reflect it being disabled.
// :active - "Press" the button down when clicked.
The processor loops thought the markup code and add the attributes for $modifiers
.
View the result It is cleaner, less duplication and easy to see different variations of an element.
or watch this kss-node-template with more multi-line descriptions and examples.
What do you think about this feature?
This is an open discussion. Is this possible with handlebars? Useful / Useless...
Greets,
m5o
Hi,
a colleague of mine came across the problem that, when not using assets, 0.2.6 throws the following error:
Running "sassdown:styleguide" (sassdown) task
Warning: Cannot call method 'forEach' of undefined Use --force to continue.
TypeError: Cannot call method 'forEach' of undefined
at Object.module.exports.writeOut (/Users/marcdix/projects/node/tests/sassdown/node_modules/sassdown/tasks/libs/sassdown.js:329:28)
at Object.module.exports.readme (/Users/marcdix/projects/node/tests/sassdown/node_modules/sassdown/tasks/libs/sassdown.js:247:14)
at Object.<anonymous> (/Users/marcdix/projects/node/tests/sassdown/node_modules/sassdown/tasks/sassdown.js:58:18)
at Object.<anonymous> (/Users/marcdix/projects/node/tests/sassdown/node_modules/grunt/lib/grunt/task.js:264:15)
at Object.thisTask.fn (/Users/marcdix/projects/node/tests/sassdown/node_modules/grunt/lib/grunt/task.js:82:16)
at Object.<anonymous> (/Users/marcdix/projects/node/tests/sassdown/node_modules/grunt/lib/util/task.js:301:30)
at Task.runTaskFn (/Users/marcdix/projects/node/tests/sassdown/node_modules/grunt/lib/util/task.js:251:24)
at Task.<anonymous> (/Users/marcdix/projects/node/tests/sassdown/node_modules/grunt/lib/util/task.js:300:12)
at /Users/marcdix/projects/node/tests/sassdown/node_modules/grunt/lib/util/task.js:227:11
at process._tickCallback (node.js:419:13)
Aborted due to warnings.
This is caused by a missing check in lib/sassdown.js
before looping Sassdown.config.assets
which might be undefined
at that point.
This check has already been added to the current master branch but not published to the npm registry yet, so I'd suggest either publishing a new version (if applicable) or publishing a bugfix as 0.2.7 to the registry.
With the current version of Sassdown, when not specifing assets in the Grunt-Options even the examples from Readme.md will not work when installing Sassdown via npm install sassdown --save-dev
.
Others: If you need this plugin badly, add the repository instead of the version to your package.json. By doing so, you bypass the registry and install the latest latest latest Sassdown directly from github. Please bear in mind to drop in now and then to check if it's fixed an replace it by the version as it's no good practice to use the repo directly.*
"devDependencies": {
"sassdown": "git://github.com/nopr/sassdown.git#master"
}
Best
Marc
Placing an absolute max-height
style on the code block is too restrictive. The block should be allowed to expand to accommodate any size code block.
By parsing code through Prism before compiling the template (#22), we can significantly reduce the required markup. We can also differentiate between sources further by renaming to markup
and source
, rather than source
and cssSource
(as it may not always be CSS).
{{#if source}}
<div class="source language-markup" data-source-type="html">
{{{source}}}
</div>
{{/if}}
{{#if cssSource}}
<div class="source language-{{prismLang}}" data-source-type="{{fileExt}}">
{{{cssSource}}}
</div>
{{/if}}
When using sassdown without custom template enabled, the iframe ID's generate a random ID like: iframe_abcde , but when I use the latest template.hbs It creates numerical ID's like: iframe0, iframe1, etc.. Is the former meant to prevent caching, because I do have some browser caching issues using Firefox.
No available reference on how to template or layout the styleguide
Navigation items and menus should reflect the current page that is open. Whether that is through a Handlebars conditional (eg. {{#if isActive}}
) or native nodejs solution before compiling the template. The latter would probably be best, to reduce the amount of markup and logic needed to write a template file.
The existing File object contains several properties which are used only once, or sometimes not at all, and these could be removed for cleaner output. Some repeatedly conflict and duplicate properties in the Config object.
Example: prismLang
can be removed during #22
We can remove site
and groups
by consolidating the Config
object.
{
slug: '_alerts',
heading: 'Alerts',
group: 'objects',
path: 'public/styleguide/objects/_alerts.html',
url: '/public/styleguide/objects/_alerts.html',
original: 'assets/sass/partials/objects/_alerts.scss',
prismLang: 'scss', // syntax highlight
ext: 'scss' // file extension
site: {
root: 'styleguide/',
rootUrl: '/public/styleguide/',
groups: {
modules: [Object],
objects: [Object]
},
assets: '../../styleguide/assets/'
},
sections: [
{
id: 'cr3sor', // randomly generated
prismLang: 'scss', // syntax highlight
fileExt: 'scss' // file extension
comment: '<h1>Alerts</h1>\n<p>Creates an alert box notification using the <code>.alert-</code> prefix. The following options are available:</p>',
source: '<pre><code><div class="alert-success">Success</div>\n<div class="alert-warning">Warning</div>\n<div class="alert-error">Error</div></code></pre>',
cssSource: '<pre><code>@mixin alert($colour){\n color: darken($colour, 50%);\n background: $colour;\n border-radius: 5px;\n margin-bottom: 1em;\n padding: 1em;\n}\n\n.alert-success { @include alert(#e2f3c1) }\n.alert-warning { @include alert(#fceabe) }\n.alert-error { @include alert(#ffdcdc) }</code></pre>'
result: '<div class="alert-success">Success</div> <div class="alert-warning">Warning</div> <div class="alert-error">Error</div>'
}
]
}
In order to reduce style conflicts and safely sandbox elements, examples currently render into an iframe
. This process is slightly complicated by the need to preserve indentation, linebreaks, whitespace and syntax highlighting.
We do this by writing the {{ result }}
into a script
element, then inserting that innerHTML
into the iframe
before removing the placeholder nodes from the DOM. This is messy and can be abstracted out of the actual .hbs file.
Current:
{{#if comment}}
<div class="comment">{{{comment}}}</div>
{{/if}}
{{#if result}}
<div class="result">
<iframe id="iframe{{@index}}" height="0" src="about:blank"></iframe>
<script id="result{{@index}}" type="text/html">{{{result}}}</script>
<script id="script{{@index}}">
var iframe = document.getElementById('iframe{{@index}}');
var script = document.getElementById('script{{@index}}');
var result = document.getElementById('result{{@index}}');
var context = iframe.contentWindow.document;
context.open();
context.write('<!DOCTYPE html>');
context.write('<'+'html>');
context.write(' <'+'head>');
context.write(' {{> assets}}');
context.write(' <'+'/'+'head>');
context.write(' <'+'body>');
context.write(result.innerHTML);
context.write(' <'+'/'+'body>');
context.write('<'+'/'+'html>');
context.close();
iframe.removeAttribute('id')
result.parentNode.removeChild(result);
script.parentNode.removeChild(script);
</script>
</div>
{{/if}}
{{#if markup}}
<div class="markup">{{{markup}}}</div>
{{/if}}
{{#if styles}}
<div class="styles">{{{styles}}}</div>
{{/if}}
Desired:
{{#if comment}}
<div class="comment">{{{comment}}}</div>
{{/if}}
{{#if result}}
<div class="result">{{{result}}}</div>
{{/if}}
{{#if markup}}
<div class="markup">{{{markup}}}</div>
{{/if}}
{{#if styles}}
<div class="styles">{{{styles}}}</div>
{{/if}}
Currently, if a folder other than the project root is used as the 'base path' for a local server, assets defined in the Grunt task cannot be found as they depend on an absolute path from the project root.
See specific comment: #29 (comment)
Provide an ignore_partials
option within the Grunt task definition. This would be an array of Sass partials to be excluded when generating the styleguide pages.
This will provide a greater degree of control over what gets rendered to the styleguide. Partials containing Sass variables for example do not need to be included in the styleguide.
sassdown: {
options: {
template_assets: 'src/styleguide/assets',
template_html: 'src/styleguide/template.hbs',
css_output: 'assets/build/css/enhanced.min.css',
ignore_partials: ['_settings-core.scss', '_settings-enhanced.scss']
},
Trying to figure out, how to structure files and styleguide. Correct me if i'm wrong.
So, know we use files as a base for our structure for styleguide. First-level folders become our main menu items in styleguide, and all the files in this first-level folders - parts of a dropdown, second level?
Or can we alter this somehow (i don't know if i need this, just asking)? Say, something like "This two files buttons1.scss
and buttons2.scss
must be in part "buttons" of a styleguide".
Hi!
First of all: nice plugin!
Would be even nicer if I could use the <pre>
element with new lines.
I have these lines in my comment (surrounded with three `):
<pre><code>function getJelly() {
echo $aDeliciousSnack;
}</code></pre>
but the code output is this:
<pre><code>function getJelly() { echo $aDeliciousSnack;}</code></pre>
Am I doing something wrong? Is it a bug?
Github Flavoured Markdown. Maybe as a true/false in options
?
Working on documenting within comments and noticed a problem with rendering.
<div class="twelve sample">Twelve Columns</div>
Works just fine, but if I try to do
<div class="row">
<div class="twelve sample">Twelve Columns</div>
</div>
I see the wrapping div rendered as text in my styleguide, it doesn't compile to HTML. Here's a screenshot.
Current method of writing out navigation structures is unwieldy and obtuse, using three custom helpers.
<div class="navigation">
<div class="gutter">
<div class="group {{#if_group ''}}is-active{{/if_group}}">
<a href="{{ page.site.rootUrl }}">Home</a>
</div>
{{#each page.site.groups}}
<div class="group {{#if_name ../group}}is-active{{/if_name}}">
<span>{{ name }}</span>
<ul>
{{#each pages}}
<li><a class="{{#if_path ../../path}}is-active{{/if_path}}" href="{{ url }}">{{ heading }}</a></li>
{{/each}}
</ul>
</div>
{{/each}}
</div>
</div>
See #44
Sassdown will add to the node tree files and directories that were not defined as part of the Grunt task. It appears that anything within the cwd
is iterated through, not just the expanded src
matches.
files: [{
expand: true,
cwd: "app/assets/stylesheets",
src: [
"modules/**/*.{scss,sass}",
"partials/**/*.{scss,sass}",
"sections/**/*.{scss,sass}"
],
dest: "public/styleguide/"
}]
I recently tried to get sassdown running, and was wondering why the iframe wasn't created.
For example, it failed with
/*
Alerts
======
Creates an alert box notification using the `.alert-` prefix. The following options are available:
<p class="alert-success">Winning</p>
<p class="alert-warning">Steady</p>
<p class="alert-error">Oh Shit!</p>
*/
@mixin alert($colour){
color: darken($colour, 50%);
background: $colour;
border-radius: 5px;
margin-bottom: 1.2em;
padding: 1em;
}
.alert-success { @include alert(#e2f3c1) }
.alert-warning { @include alert(#fceabe) }
.alert-error { @include alert(#ffdcdc) }
The code seemed perfectly valid to me, but I found that when using only one tab
for intendation, the markup snipped wasn't recognized. Only after adding a second one, sassdown did its magic ;)
Maybe you could add this to the documentation? Or even allow a single tab for intendation?
I'm contributing code and want to use Array.forEach which isn't supported in IE8. It would be good to know which browsers I'm suposed to support in cases like this.
I've just pushed the latest code to my repo - https://github.com/sturobson/Squeeler
when compiling and watching (look at _alerts.scss for the example) I get this error
' +''); context.close(); script.parentNode.removeChild(script);
after the iframe in the results div with a script id of "script_ioedk". I've completely restarted the npm install stuff, deleting anything that's pulled down and started it again. But this still happens.
Any ideas?
given the following comment:
/*
* Headings
* ==========
*
* Headings examples ranging from H1-H4.
*
* <h1>Heading 1</h1>
* <h2>Heading 2</h2>
* <h3>Heading 3</h3>
* <h4>Heading 4</h4>
*/
I expect the output to be
Headings examples ranging from H1-H4.
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
Instead, the output is:
The rendered HTML:
<div class="comment">
<ul>
<li>Headings</li>
<li>==========*</li>
<li>Headings examples ranging from H1-H4.*</li>
<li><h1>Heading 1</h1></li>
<li><h2>Heading 2</h2></li>
<li><h3>Heading 3</h3></li>
<li><h4>Heading 4</h4></li>
</ul>
</div>
any thoughts on how to remedy this?
The template.hbs file uses a variable to store the path to the assets folder - the parent folder of the CSS and JavaScript files (see below)
This {{site.assets}}
variable resolves with backslashes rather than forward slashes which causes problems with some browsers on a Windows platform. For example Firefox cannot resolve the file path with a mixture of back and forward slashes - it requires forward slashes to be used.
See screen grab below from the Chrome Dev Tools Inspector for how the above file paths actually resolve.
One of the last commits broke the iframe height detection for some elements.
Probably this is caused by #65.
Also these changes were added to the same npm version. Better would be to release 0.2.7 or 0.3.0 ;)
Hello,
I don't know if thats technically possible, but it would be reeeally cool if I could "print " variables in my comments. I can't do that with Sass alone because comments are not compiled.
What I want to use is the following
/*
# Test
Use #{$buttonClass} for a button. The primary color is #{$colorPrimary}
*/
Greetings
Currently, the ids of iframes and scripts are generated randomly:
id: Math.random().toString(36).substr(2,5)
This means when the styleguide is generated, a lot of changes will appear in a git history even though no scss file has been modified between two runs.
Would it be possible to generates these ids from a hash of the content, so that unchanged scss files generate identical styleguides?
thanks!
It could be really useful to be able to output scripts at the bottom of the body. Doing so make it unnecessary to add $(document).ready..
to each scripts.
On my setup I quickly fixed it by splitting the localAssets in the writeOut
function and added 2 helpers (scripts and styles). Now I think it would be better to add an option footerAssets
just like assets
. This would be more flexible and would add less complexity.
What do you think?
If the user leaves options.template_html
blank the task fails. Plugin should default to own, internal version but remind the user they can/should create one.
The npm module is versioned, you even write the latest version number into the readme.
Imo you should also tag the repo with the version numbers.
If the user does not specifiy option.template_assets
the styleguide renders unstyled - a default stylesheet should be provided.
Groups can be removed wholesale when #24 is completed.
Hey! Totally digging this plugin and I have a few suggestions. Would love to know your reasoning for the same.
.theme
or something so that it doesn't interfere with styleguide CSS._buttons.scss
root
- button
-- _mixins.scss
-- _extends.scss
-- _buttons.scss
-- _variables.scss
Currently, the config.tree
is a hack as it contains both File objects (which contain config.tree
, creating a circular). In order to reduce complexity, we could combine the two and store all File data within a tree object.
Related: #23
Would it be possible include a developer mode to associate the line numbers and file to a given section where by the developer could click on the MD/Scss and save back to the file or revert the changes they've just made?
This would open it up to other tasks to watch for edits, compile and live reload the style guide so developers could make amends a lot quicker.
fetched the latest version 0.2.6. Here are some example file, covered the bug.
assets/stylesheets/partials/_alerts.scss
:
/*
# Alerts
basic stuff
<div class="alert">alert</div>
*/
.alert {
border: 1px solid;
}
/*
# Alert Colors
color stuff
<div class="alert alert-danger">alert</div>
*/
.alert-danger {
border-color: red;
}
The Stylesheet generation is fine. The Title in the Navigation will be overwritten with the last h1 in the markdown. So in this example Alert Colors
is the Title, not Alerts
. This is different to the previous version.
I would suggest an fictitious nopr/sassdown-example repo. Maybe a Rails app, pushed to heroku (free) to test and see the current released version under real conditions. I'll contribute to this if you give me the push rights to the example repo.
The first comment block in the Sass partial is used to denote the <h1>
for the style guide page.
If a blank line is added after the opening comment block like so...
/*
My Module
=========
*/
...then the <h1>
title is used in the dropdown navigation rather than the Sass partial name i.e. My Module
appears in the navigation rather than _my-module
.
However if that extra blank line is not added after the opening comment block e.g.
/*
My Module
=========
*/
then the Sass partial name is not replaced by this title and remains as the Sass partial name.
I think zero, one or many blank lines should be permissible in the opening comment block before the title.
Perhaps tie into #14
If options.assets is empty, the task fails to execute.
Sorry for the second feature request in this week. Like to share my thought...
This time, it is a feature I saw on the trulia/hologram styleguide repository. They use YAML front-matter syntax to specify vars or custom metadata.
YAML front matter is quite popular, read more:
Think of this optional section that is placed at the beginning of an documentation block. It is for optional metadata that will be extend the Page Object in some way.
Goal is to access this variable section somewhere in the handlebar templates.
In this Example you define metadata for the iframe context in the template.hbs.
I would be cool if it's possible to extend the generated iframe with this parameters.
/*
---
body_class: article
assets:
- public/styleguide/article_styles.css
---
Alerts
======
Creates an alert box notification using the `.alert-` prefix. The following options are available:
<div class="alert-success">Success</div>
<div class="alert-warning">Warning</div>
<div class="alert-error">Error</div>
*/
This then can be parsed with something like this. (I am a handlebar noob)
Hope you can guess the wanted result. Want to filter the inclusion of specific assest and define a custom body class attribute.
<html>
<head>
<!-- use result.assets if any otherwise global assets -->
{{> assets ||= result.assets}}'
</head>
<body class="{{result.meta.body_class}}">
{{result}}
</body>
</html>
What do you think? :]
Greets,
m5o
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.