├── .editorconfig ├── .gitignore ├── .jscsrc ├── .jshintignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── LICENSE ├── index.js ├── package.json ├── readme.md └── test ├── mocha.opts ├── test.css ├── test.html ├── test.js ├── test2.css ├── testRemoveAll.html ├── testRemoveAttrs.html └── testRemoveTag.html /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs. 2 | # More information at http://EditorConfig.org 3 | 4 | # No .editorconfig files above the root directory 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | indent_size = 4 10 | end_of_line = lf 11 | indent_style = space 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.{bemjson.js,deps.js}] 16 | indent_size = 4 17 | 18 | [{bower,package}.json] 19 | indent_size = 2 20 | 21 | [*.md] 22 | trim_trailing_whitespace = false 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | .DS_Store 3 | ._* 4 | 5 | # NODEJS 6 | node_modules 7 | npm-debug.log 8 | .nyc_output 9 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "disallowSpacesInCallExpression": true, 3 | "disallowSpaceAfterObjectKeys": true, 4 | "disallowNewlineBeforeBlockStatements": true, 5 | "disallowMultipleLineBreaks": true, 6 | "requireSemicolons": true, 7 | "requireFunctionDeclarations": true, 8 | "requireCommaBeforeLineBreak": true, 9 | "disallowTrailingComma": true, 10 | "disallowTrailingWhitespace": true, 11 | "disallowSpacesInFunction": { 12 | "beforeOpeningRoundBrace": true 13 | }, 14 | "requireSpacesInFunction": { 15 | "beforeOpeningCurlyBrace": true 16 | }, 17 | "disallowSpacesInConditionalExpression": { 18 | "afterTest": true, 19 | "afterConsequent": true 20 | }, 21 | "excludeFiles": [ 22 | ".git/**", 23 | "node_modules/**" 24 | ], 25 | "fileExtensions": [".js"] 26 | } 27 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "eqeqeq": true, 3 | "expr": true, 4 | "maxlen": 120, 5 | "undef": true, 6 | "unused": true, 7 | "node": true 8 | } 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | test/ 3 | npm-debug.log 4 | .editorconfig 5 | .jscsrc 6 | .jshintignore 7 | .jshintrc 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "node" 5 | - "lts/*" 6 | - "8" 7 | 8 | after_script: 9 | - npm run coverage 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 PostHTML Ivan Voischev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | module.exports = function posthtmlStyleToFile(options) { 5 | options = options || { path: './result.css' }; 6 | 7 | var buf = ''; 8 | 9 | return function(tree) { 10 | 11 | tree.match({ tag: 'style' }, function(node) { 12 | buf += node.content[0].trim() || ''; 13 | 14 | if (options.removeStyle === 'tag' || options.removeStyle === 'all') { 15 | return ''; 16 | } 17 | 18 | return node; 19 | }); 20 | 21 | tree.match({ attrs: { style: true }}, function(node) { 22 | var cls = ''; 23 | node.attrs.class && 24 | (cls = '.' + (node.attrs.class.split(' ')).join('.')); 25 | 26 | buf += '\n' + 27 | node.tag + 28 | (node.attrs.id? ('#' + node.attrs.id ): '') + 29 | cls + '{' + node.attrs.style + '}'; 30 | 31 | if (options.removeStyle === 'attrs' || options.removeStyle === 'all') { 32 | delete node.attrs.style; 33 | } 34 | 35 | return node; 36 | }); 37 | 38 | fs.writeFile(path.resolve(options.path), buf, 'utf-8', function(error) { 39 | if (error) throw error; 40 | }); 41 | 42 | return tree; 43 | }; 44 | }; 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "posthtml-style-to-file", 3 | "version": "0.2.0", 4 | "description": "posthtml style-to-file plugin", 5 | "main": "index.js", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "chai": "^4.2.0", 9 | "coveralls": "^3.0.4", 10 | "jscs": "^3.0.7", 11 | "jshint": "^2.8.0", 12 | "mocha": "^6.1.4", 13 | "nyc": "^14.1.1", 14 | "posthtml": "^0.11.4" 15 | }, 16 | "scripts": { 17 | "coverage": "nyc report --reporter=text-lcov | coveralls", 18 | "test": "npm run lint && nyc mocha", 19 | "lint": "jshint . && jscs . -v" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/posthtml/posthtml-style-to-file.git" 24 | }, 25 | "keywords": [ 26 | "html", 27 | "xml", 28 | "css", 29 | "file", 30 | "convert", 31 | "style-to-file", 32 | "postproccessor", 33 | "parser", 34 | "transform", 35 | "manipulation" 36 | ], 37 | "author": "Ivan Voischev ", 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/posthtml/posthtml-style-to-file/issues" 41 | }, 42 | "homepage": "https://github.com/posthtml/posthtml-style-to-file#readme" 43 | } 44 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![NPM][npm]][npm-url] 2 | [![Deps][deps]][deps-url] 3 | [![Tests][travis]][travis-url] 4 | [![Coverage][cover]][cover-url] 5 | 6 |
7 | 8 | 9 |

Style-to-File Plugin

10 |

Save DOM styles to CSS file

11 |
12 | 13 |

Install

14 | 15 | ```bash 16 | npm i -D posthtml-style-to-file 17 | ``` 18 | 19 |

Usage

20 | 21 | ## Options 22 | 23 | #### `path` 24 | 25 | Type: `String` 26 | Default: `./result.css` 27 | Description: *Destination path, where the extracted CSS is saved to.* 28 | 29 | #### `removeStyle` 30 | 31 | Type: `String` 32 | Default: `` 33 | Description: *Removes the specified value `attrs` | `tag` | `all`* 34 | 35 | __`removeStyle`__ 36 | 37 | Destination path, where the extracted CSS is saved to. 38 | 39 |

Example

40 | 41 | ```js 42 | const posthtml = require('posthtml') 43 | const styleToFile = require('posthtml-style-to-file') 44 | 45 | const html = readFileSync('path/to/html', 'utf8') 46 | 47 | posthtml([ styleToFile({ path: './dist/style.css' }) ]) 48 | .process(html) 49 | .then((result) => console.log(result.html)) 50 | ``` 51 | 52 | __index.html__ 53 | 54 | ```html 55 | 56 | 57 | Wow 58 | 61 | 62 | 63 |
64 |
65 | Text 66 |
67 |
68 | 69 | 70 | ``` 71 | 72 | __style.css__ 73 | 74 | ```css 75 | html{ margin: 0 } 76 | body{ background: #fff; } 77 | div.button{ border: 1px solid #000; } 78 | ``` 79 | 80 | [npm]: https://img.shields.io/npm/v/posthtml-style-to-file.svg 81 | [npm-url]: https://npmjs.com/package/posthtml-style-to-file 82 | 83 | [deps]: https://david-dm.org/posthtml/posthtml-style-to-file.svg 84 | [deps-url]: https://david-dm.org/posthtml/posthtml-style-to-file 85 | 86 | [style]: https://img.shields.io/badge/code%20style-standard-yellow.svg 87 | [style-url]: http://standardjs.com/ 88 | 89 | [travis]: http://img.shields.io/travis/posthtml/posthtml-style-to-file.svg 90 | [travis-url]: https://travis-ci.org/posthtml/posthtml-style-to-file 91 | 92 | [cover]: https://coveralls.io/repos/github/posthtml/posthtml-style-to-file/badge.svg 93 | [cover-url]: https://coveralls.io/github/posthtml/posthtml-style-to-file 94 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --inline-diffs 2 | --reporter spec 3 | -------------------------------------------------------------------------------- /test/test.css: -------------------------------------------------------------------------------- 1 | html{ margin: 0 } 2 | body{background: #fff;} 3 | section#main{width: 800px; margin: auto;} 4 | div.button{border: 1px solid #000;} -------------------------------------------------------------------------------- /test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Wow 4 | 7 | 8 | 9 |
10 |
11 |
12 | Text 13 |
14 |
15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* jshint mocha: true, maxlen: false */ 2 | var posthtml = require('posthtml'); 3 | var plugin = require('..'); 4 | var expect = require('chai').expect; 5 | var fs = require('fs'); 6 | 7 | var HTML = fs.readFileSync('./test/test.html', 'utf-8'); 8 | var CSS = fs.readFileSync('./test/test.css', 'utf-8'); 9 | 10 | function test(html, options, callbackSuccess, callbackError) { 11 | posthtml() 12 | .use(plugin(options)) 13 | .process(html) 14 | .then(callbackSuccess) 15 | .catch(callbackError); 16 | } 17 | 18 | describe('Simple test', function() { 19 | it('style to file', function(done) { 20 | test( 21 | HTML, 22 | { path: './test/test2.css' }, 23 | function() { 24 | setTimeout(function() { 25 | expect(CSS).to.eql(fs.readFileSync('./test/test2.css', 'utf-8').toString()); 26 | done(); 27 | }, 20); 28 | }, 29 | function(error) { 30 | done(error); 31 | } 32 | ); 33 | }); 34 | 35 | it('remove style attrs', function(done) { 36 | test( 37 | HTML, 38 | { 39 | path: './test/test2.css', 40 | removeStyle: 'attrs' 41 | }, 42 | function(result) { 43 | setTimeout(function() { 44 | expect(result.html).to.eql(fs.readFileSync('./test/testRemoveAttrs.html', 'utf-8').toString()); 45 | done(); 46 | }, 20); 47 | }, 48 | function(error) { 49 | done(error); 50 | } 51 | ); 52 | }); 53 | 54 | it('remove style tag', function(done) { 55 | test( 56 | HTML, 57 | { 58 | path: './test/test2.css', 59 | removeStyle: 'tag' 60 | }, 61 | function(result) { 62 | setTimeout(function() { 63 | expect(result.html).to.eql(fs.readFileSync('./test/testRemoveTag.html', 'utf-8').toString()); 64 | done(); 65 | }, 20); 66 | }, 67 | function(error) { 68 | done(error); 69 | } 70 | ); 71 | }); 72 | 73 | it('remove style all', function(done) { 74 | test( 75 | HTML, 76 | { 77 | path: './test/test2.css', 78 | removeStyle: 'all' 79 | }, 80 | function(result) { 81 | setTimeout(function() { 82 | expect(result.html).to.eql(fs.readFileSync('./test/testRemoveAll.html', 'utf-8').toString()); 83 | done(); 84 | }, 20); 85 | }, 86 | function(error) { 87 | done(error); 88 | } 89 | ); 90 | }); 91 | }); 92 | -------------------------------------------------------------------------------- /test/test2.css: -------------------------------------------------------------------------------- 1 | html{ margin: 0 } 2 | body{background: #fff;} 3 | section#main{width: 800px; margin: auto;} 4 | div.button{border: 1px solid #000;} -------------------------------------------------------------------------------- /test/testRemoveAll.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Wow 4 | 5 | 6 | 7 |
8 |
9 |
10 | Text 11 |
12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /test/testRemoveAttrs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Wow 4 | 7 | 8 | 9 |
10 |
11 |
12 | Text 13 |
14 |
15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /test/testRemoveTag.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Wow 4 | 5 | 6 | 7 |
8 |
9 |
10 | Text 11 |
12 |
13 |
14 | 15 | 16 | --------------------------------------------------------------------------------