Skip to content

Commit 6ee2240

Browse files
committed
initial commit
0 parents commit 6ee2240

File tree

10 files changed

+209
-0
lines changed

10 files changed

+209
-0
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.DS_Store
2+
npm-debug.log
3+
node_modules

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## 0.1.0 - First Release
2+
* Initial version

LICENSE.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2016 <Your name here>
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# atom html-to-css package
2+
3+
Generates CSS boilerplate based on the selected HTML.
4+
5+
Early & opinionated version:
6+
- Only cares about classes, ignores id's/other possible selectors
7+
- Outputs flat CSS structure
8+
- ... with optional classless first-child element nesting
9+
- Indents with 2 spaces
10+
- Made primarily to simplify working with BEM methodology
11+
12+
# demo
13+
14+
![atom html to css](http://dracul.kill.pl/~ard/htmltocss.gif)
15+
16+
Future: I'll extend it with different transformers/formatters as settings. Contributions welcomed.

lib/formatter.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function saveElement(css, el) {
2+
css = css + "." + el.name + " {\n\n";
3+
if (el.children && el.children.length) {
4+
el.children.map((ch) => {
5+
css = css + "\t" + ch + " {\n\n\t}\n";
6+
});
7+
}
8+
css = css + "}\n\n";
9+
return css;
10+
}
11+
12+
exports.format = function(json) {
13+
const css = "";
14+
return json.reduce(saveElement, css);
15+
}

lib/html-to-css.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use babel';
2+
3+
import htmlparser from 'htmlparser2';
4+
import { CompositeDisposable } from 'atom';
5+
import { transform } from './transformer';
6+
import { format } from './formatter';
7+
8+
export default {
9+
10+
config: {
11+
"nest-classless": {
12+
"type": "boolean",
13+
"default": true,
14+
"description": "Nest first-child classless elements (.someClass { p {} }})"
15+
}
16+
},
17+
18+
subscriptions: null,
19+
20+
activate(state) {
21+
this.subscriptions = new CompositeDisposable();
22+
this.subscriptions.add(atom.commands.add('atom-workspace', {
23+
'html-to-css:generate': () => this.generate()
24+
}));
25+
},
26+
27+
deactivate() {
28+
this.subscriptions.dispose();
29+
},
30+
31+
serialize() {
32+
},
33+
34+
generate() {
35+
const pane = atom.workspace.getActivePane();
36+
const editor = pane.getActiveEditor();
37+
const text = editor.getSelectedText();
38+
const htmlJson = htmlparser.parseDOM(text);
39+
const preparedJson = transform(htmlJson);
40+
const css = format(preparedJson);
41+
if (css) {
42+
atom.clipboard.write(css);
43+
atom.notifications.addSuccess('CSS boilerplate copied to clipboard.');
44+
} else {
45+
atom.notifications.addError('Parsing failed');
46+
}
47+
}
48+
};

lib/transformer.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
function parseArray(arr, tree) {
2+
return arr.map((el) => {
3+
parseNode(tree, el);
4+
});
5+
}
6+
7+
function splitClasses(classNames) {
8+
return classNames.split(" ");
9+
}
10+
11+
function storeElement(store, className, obj) {
12+
13+
const ret = {
14+
name: className
15+
};
16+
17+
let val = false;
18+
if (obj.children && atom.config.get('html-to-css.nest-classless')) {
19+
val = obj.children.filter((el) => {
20+
return el.type === 'tag' && !el.attribs.class
21+
}).reduce((acc, cur) => {
22+
return [cur.name, ...acc];
23+
}, []);
24+
ret.children = [ ...new Set(val) ];
25+
}
26+
if (!store.find((el) => el.name === ret.name)) store.push(ret);
27+
}
28+
29+
function parseNode(store, node) {
30+
if (node.type !== 'tag') return;
31+
if (node.attribs.class) {
32+
const classes = splitClasses(node.attribs.class);
33+
classes.map((className) => {
34+
storeElement(store, className, node);
35+
});
36+
}
37+
if (node.children.length) {
38+
return parseArray(node.children, store);
39+
} else {
40+
return store;
41+
}
42+
}
43+
44+
exports.transform = function(json) {
45+
const store = [];
46+
parseArray(json, store);
47+
return store;
48+
}

menus/html-to-css.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"context-menu": {
3+
"atom-text-editor": [
4+
{
5+
"label": "HTML-to-CSS: Generate",
6+
"command": "html-to-css:generate"
7+
}
8+
]
9+
},
10+
"menu": [
11+
{
12+
"label": "Packages",
13+
"submenu": [
14+
{
15+
"label": "html-to-css",
16+
"submenu": [
17+
{
18+
"label": "Generate",
19+
"command": "html-to-css:generate"
20+
}
21+
]
22+
}
23+
]
24+
}
25+
]
26+
}

package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "html-to-css",
3+
"main": "./lib/html-to-css",
4+
"version": "0.0.0",
5+
"description": "A short description of your package",
6+
"keywords": [],
7+
"author": "Szymon Pilkowski <szymon.pilkowski@gmail.com>",
8+
"activationCommands": {
9+
"atom-workspace": "html-to-css:generate"
10+
},
11+
"repository": "https://github.com/ardcore/atom-html-to-css",
12+
"license": "MIT",
13+
"engines": {
14+
"atom": ">=1.0.0 <2.0.0"
15+
},
16+
"dependencies": {
17+
"htmlparser2": "^3.9.0"
18+
}
19+
}

0 commit comments

Comments
 (0)