├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .mversion ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── appveyor.yml ├── index.js ├── lib ├── line.js ├── msg.js ├── title.js └── type.js ├── package-lock.json ├── package.json └── test ├── expect └── index.html ├── fixtures ├── .htmlhintrc └── index.html ├── index.js └── lib ├── line.js ├── msg.js ├── title.js └── type.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_size = 2 6 | end_of_line = lf 7 | indent_style = space 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [{bower,package}.json] 12 | indent_size = 2 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Problem 2 | 3 | Briefly describe the issue you are experiencing (or the feature you want to see 4 | added to the plugin). Tell us what you were trying to do and what happened 5 | instead. Remember, this is _not_ a place to ask questions. For that, go to 6 | http://gitter.im/posthtml/posthtml 7 | 8 | ## Details 9 | 10 | Describe in more detail the problem you have been experiencing, if necessary. 11 | 12 | ## Error Logs 13 | 14 | Create a [gist](https://gist.github.com) which is a paste of your **full** 15 | logs(_result.tree_ (PostHTML Tree), _result.html_ (HTML)), and link them here. 16 | Do **not** paste your full logs here, as it will make this issue long and hard 17 | to read! If you are reporting a bug, **always** include logs! 18 | 19 | ## Issue [ Code ] 20 | 21 | Please remember that, with sample code; it's easier to reproduce bug and much 22 | faster to fix it. 23 | 24 | Please refer to a simple code example. 25 | 26 | ```bash 27 | $ git clone https://github.com// 28 | ``` 29 | 30 | ## Environment 31 | 32 | Please provide information about your environment. 33 | 34 | | OS | Node | npm | PostHTML | 35 | |:------------:|:-----:|:-------:|:--------:| 36 | | OS X 10.11.4 | 6.0.0 | 3.9.0 | 0.8.7 | 37 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Proposed Changes 2 | 3 | Describe the big picture of your changes here to communicate to the maintainers 4 | why we should accept this pull request. If it fixes a bug or resolves a feature 5 | request, be sure to link to that issue. 6 | 7 | ## Types of Changes 8 | 9 | What types of changes does your code introduce 10 | _Put an `x` in the boxes that apply_ 11 | 12 | - [ ] Bug (non-breaking change which fixes an issue) 13 | - [ ] Feature (non-breaking change which adds functionality) 14 | - [ ] Breaking Change (fix or feature which changes existing functionality) 15 | 16 | ## Checklist 17 | 18 | _Put an `x` in the boxes that apply. You can also fill these out after creating 19 | the PR. If you're unsure about any of them, don't hesitate to ask. We're here to 20 | help! This is a reminder of what we are going to look for before merging your 21 | code._ 22 | 23 | - [ ] I have read the [CONTRIBUTING](/CONTRIBUTING.md) guide 24 | - [ ] Lint and unit tests pass with my changes 25 | - [ ] I have added tests that prove my fix is effective/works 26 | - [ ] I have added necessary documentation (if appropriate) 27 | - [ ] Any dependent changes are merged and published in downstream modules 28 | 29 | ## Further Comments 30 | 31 | If this is a large or complex change, kick off the discussion by explaining why 32 | you chose the solution you did and what alternatives you considered, etc... 33 | 34 | ### Reviewers: @michael-ciniawsky, ... 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | 3 | .DS_Store 4 | ._* 5 | 6 | # NODEJS 7 | 8 | .nyc_output 9 | 10 | npm-debug.log 11 | 12 | coverage 13 | node_modules 14 | -------------------------------------------------------------------------------- /.mversion: -------------------------------------------------------------------------------- 1 | { 2 | "commitMessage": "chore(ver): v%s", 3 | "scripts": { 4 | "postcommit": "git push && git push --tags && npm run pack && npm run dmg", 5 | "precommit": "conventional-changelog -p angular -i CHANGELOG.md -s && git add ." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # FILES 2 | 3 | .travis.yml 4 | .gitignore 5 | .editorconfig 6 | 7 | CHANGELOG.md 8 | CONTRIBUTING.md 9 | README.md 10 | 11 | *.test.js 12 | 13 | npm-debug.log 14 | 15 | # DIRECTORIES 16 | 17 | .github 18 | .nyc_output 19 | 20 | test 21 | coverage 22 | node_modules 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "10" 5 | 6 | os: 7 | - linux 8 | - osx 9 | 10 | env: 11 | matrix: 12 | - NODE_VERSION="10" 13 | 14 | matrix: 15 | fast_finish: true 16 | 17 | install: 18 | - npm install 19 | 20 | script: 21 | - npm test 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 (INITIAL_DATE) 2 | 3 | - Added: Initial version 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Contributions welcome! 4 | 5 | **Before spending lots of time on something, ask for feedback on your idea 6 | first!** 7 | 8 | Please search issues and pull requests before adding something new to avoid 9 | duplicating efforts and conversations. 10 | 11 | This project welcomes non-code contributions, too! The following types of 12 | contributions are welcome: 13 | 14 | - **Ideas**: participate in an issue thread or start your own to have your voice 15 | heard. 16 | - **Writing**: contribute your expertise in an area by helping expand the 17 | included docs. 18 | - **Editing**: fix typos, clarify language, and improve the quality of the docs. 19 | - **Formatting**: help keep docs easy to read with consistent formatting. 20 | 21 | ## Code Style 22 | 23 | [![standard][standard]][standard-url] 24 | 25 | This repository uses [`standard`][standard-url] to maintain code style and 26 | consistency, 27 | and to avoid style arguments. `npm test` runs `standard` automatically, so you 28 | don't have to! 29 | 30 | ## Project Governance 31 | 32 | Individuals making significant and valuable contributions are given 33 | commit-access to the project to contribute as they see fit. 34 | This project is more like an open wiki than a standard guarded open source 35 | project. 36 | 37 | ### Rules 38 | 39 | There are a few basic ground-rules for contributors: 40 | 41 | 1. **No `--force` pushes** or modifying the Git history in any way. 42 | 2. **Non-master branches** should be used for ongoing work. 43 | 3. **Significant modifications** like API changes should be subject to a **pull 44 | request** to solicit feedback from other contributors. 45 | 4. **Pull requests** are *encouraged* for all contributions to solicit feedback, 46 | but left to the discretion of the contributor. 47 | 48 | ### Releases 49 | 50 | Declaring formal releases remains the prerogative of the project maintainer. 51 | 52 | ### Changes to this arrangement 53 | 54 | This is an experiment and feedback is welcome! This document may also be subject 55 | to pull-requests or changes by contributors where you believe you have something 56 | valuable to add or change. 57 | 58 | ## Developer's Certificate of Origin 1.1 59 | 60 | By making a contribution to this project, I certify that: 61 | 62 | - (a) The contribution was created in whole or in part by me and I have the 63 | right to submit it under the open source license indicated in the file. 64 | 65 | - (b) The contribution is based upon previous work that, to the best of my 66 | knowledge, is covered under an appropriate open source license and I have the 67 | right under that license to submit that work with modifications, whether 68 | created in whole or in part by me, under the same open source license (unless 69 | I am permitted to submit under a different license), as indicated in the file. 70 | 71 | - (c) The contribution was provided directly to me by some other person who 72 | certified (a), (b) or (c) and I have not modified it. 73 | 74 | - (d) I understand and agree that this project and the contribution are public 75 | and that a record of the contribution (including all personal information I 76 | submit with it, including my sign-off) is maintained indefinitely and may be 77 | redistributed consistent with this project or the open source license(s) 78 | involved. 79 | 80 | [standard]: https://cdn.rawgit.com/feross/standard/master/badge.svg 81 | [standard-url]: https://github.com/feross/standard 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License (MIT) 2 | 3 | Copyright (c) 2016 PostHTML Michael Ciniawsky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![NPM][npm]][npm-url] 2 | [![Deps][deps]][deps-url] 3 | [![Coverage][cover]][cover-url] 4 | [![Standard Code Style][style]][style-url] 5 | [![Chat][chat]][chat-badge] 6 | 7 | # Hint Plugin 8 | 9 | ## Install 10 | 11 | ```bash 12 | npm i -D posthtml-hint 13 | ``` 14 | 15 | ## Usage 16 | 17 | #### Options 18 | 19 | **Rules [String|Object]** 20 | 21 | **[Rules Reference](https://github.com/yaniswang/HTMLHint/wiki/Rules)** 22 | 23 | ```js 24 | const hint = require('posthtml-hint')('./path/to/.htmlhintrc') 25 | ``` 26 | 27 | ## Example 28 | 29 | ```js 30 | const { readFileSync } = require('fs') 31 | 32 | const posthtml = require('posthtml') 33 | 34 | const hint = require('posthtml-hint')(/* options */) 35 | const html = readFileSync('./index.html', 'utf8') 36 | 37 | posthtml([ hint ]) 38 | .process(html) 39 | .then(result => console.log(result.html)) 40 | ``` 41 | 42 | #### Console 43 | 44 | ```bash 45 | PostHTML HINT 46 | ------------- 47 | 48 | ✖ error [10:12] 49 | Special characters must be escaped : [ > ]. 50 | 51 | ✖ error [12:3] 52 | Special characters must be escaped : [ < ]. 53 | 54 | ✖ error [12:21] 55 | Special characters must be escaped : [ < ]. 56 | 57 | ✖ error [12:30] 58 | Special characters must be escaped : [ > ]. 59 | 60 | ✖ error [15:17] 61 | Tag must be paired, no start tag: [ ] 62 | 63 | ⚠ 5 Errors 64 | ``` 65 | 66 | ## Maintainers 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 |
72 | 74 |
75 | Michael Ciniawsky 76 |
80 | 81 | ## Contributing 82 | 83 | See [PostHTML Guidelines](https://github.com/posthtml/posthtml/tree/master/docs) and [contribution guide](CONTRIBUTING.md). 84 | 85 | ## LICENSE 86 | 87 | [MIT](LICENSE) 88 | 89 | [npm]: https://img.shields.io/npm/v/posthtml-hint.svg 90 | [npm-url]: https://npmjs.com/package/posthtml-hint 91 | 92 | [deps]: https://david-dm.org/posthtml/posthtml-hint.svg 93 | [deps-url]: https://david-dm.org/posthtml/posthtml-hint 94 | 95 | [travis]: http://img.shields.io/travis/posthtml/posthtml-hint.svg 96 | [travis-url]: https://travis-ci.org/posthtml/posthtml-hint 97 | 98 | [cover]: https://coveralls.io/repos/github/posthtml/posthtml-hint/badge.svg?branch=master 99 | [cover-url]: https://coveralls.io/github/posthtml/posthtml-hint?branch=master 100 | 101 | [style]: https://img.shields.io/badge/code%20style-standard-yellow.svg 102 | [style-url]: http://standardjs.com/ 103 | 104 | [chat]: https://badges.gitter.im/posthtml/posthtml.svg 105 | [chat-badge]: https://gitter.im/posthtml/posthtml?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" 106 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # http://www.appveyor.com/docs/appveyor-yml 2 | 3 | version: "{build}" 4 | 5 | environment: 6 | matrix: 7 | - nodejs_version: "10" 8 | platform: x64 9 | - nodejs_version: "10" 10 | platform: x86 11 | 12 | matrix: 13 | fast_finish: true 14 | 15 | install: 16 | # Build 17 | - npm install 18 | - npm test 19 | 20 | cache: 21 | # local npm modules 22 | - 'node_modules -> package.json' 23 | 24 | build: off 25 | 26 | test: off 27 | 28 | deploy: off 29 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // ------------------------------------ 2 | // #POSTHTML - HINT 3 | // ------------------------------------ 4 | 5 | 'use strict' 6 | 7 | const fs = require('fs') 8 | const path = require('path') 9 | 10 | const chalk = require('chalk') 11 | const tab = require('text-table') 12 | const log = require('log-symbols') 13 | 14 | const render = require('posthtml-render') 15 | const HTMLHintClass = require('htmlhint').HTMLHint 16 | const htmlhint = new HTMLHintClass() 17 | 18 | const title = require('./lib/title') 19 | const type = require('./lib/type') 20 | const line = require('./lib/line') 21 | const message = require('./lib/msg') 22 | 23 | module.exports = function (options) { 24 | options = options || {} 25 | 26 | if (typeof options === 'string') { 27 | options = fs.readFileSync(path.resolve(options), 'utf8') 28 | } 29 | 30 | return function postHTMLHint (tree) { 31 | if (!tree.render) tree.render = render 32 | const messages = htmlhint.verify(tree.render(tree), options) 33 | 34 | title('\nPostHTML HINT') 35 | 36 | const table = tab(messages.map(msg => [ 37 | `\n${type(msg.type)} ${line(msg.line, msg.col)}`, 38 | `\n${message(msg.message)}` 39 | ]), { align: 'l', hsep: '' }) 40 | 41 | console.log(table) 42 | 43 | const result = messages.length 44 | 45 | if (result === 0) { 46 | console.log(chalk.green(`${log.success} ${result} Errors`)) 47 | } else { 48 | console.log(chalk.red(`\n${log.warning} ${result} Errors`)) 49 | } 50 | 51 | return tree 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/line.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | 5 | exports = module.exports = (line = 0, col = 0) => chalk.white(`[${line}:${col}]`) 6 | -------------------------------------------------------------------------------- /lib/msg.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | 5 | exports = module.exports = function (msg) { 6 | let line = '' 7 | let line2 = '' 8 | 9 | if (msg.length > 80 && msg.length <= 160) { 10 | line = msg.slice(msg.indexOf(' ', 80) + 1) 11 | 12 | msg = msg.slice(0, msg.indexOf(' ', 80)) 13 | 14 | return chalk.blue(msg.concat('\n', line)) 15 | } 16 | 17 | if (msg.length > 160) { 18 | line = msg.slice(msg.indexOf(' ', 80) + 1) 19 | line2 = line.slice(line.indexOf(' ', 80) + 1) 20 | 21 | line = line.slice(0, line.indexOf(' ', 80)) 22 | msg = msg.slice(0, msg.indexOf(' ', 80)) 23 | 24 | return chalk.blue(msg.concat('\n', line, '\n', line2)) 25 | } 26 | 27 | return chalk.blue(msg) 28 | } 29 | -------------------------------------------------------------------------------- /lib/title.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | 5 | const transform = title => chalk.white.bold.underline(title) 6 | 7 | exports = module.exports = (title) => console.log(transform(title)) 8 | exports.transform = transform 9 | -------------------------------------------------------------------------------- /lib/type.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | const log = require('log-symbols') 5 | 6 | exports = module.exports = type => chalk.red(`${log.error + ' ' + type}`) 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "posthtml-hint", 3 | "version": "0.8.3", 4 | "description": "HTML Hint for PostHTML", 5 | "engines": { 6 | "node": ">=8", 7 | "npm": ">=3" 8 | }, 9 | "main": "index.js", 10 | "scripts": { 11 | "pretest": "standard", 12 | "test": "nyc ava --verbose", 13 | "lint": "standard", 14 | "lint:fix": "standard --fix" 15 | }, 16 | "nyc": { 17 | "all": true, 18 | "require": "babel-register", 19 | "include": [ 20 | "lib", 21 | "test" 22 | ], 23 | "extension": [ 24 | ".js" 25 | ] 26 | }, 27 | "standard": { 28 | "ignore": [] 29 | }, 30 | "dependencies": { 31 | "htmlhint": "0.11.0", 32 | "log-symbols": "3.0.0", 33 | "posthtml-render": "1.1.4", 34 | "text-table": "0.2.0" 35 | }, 36 | "devDependencies": { 37 | "ava": "3.3.0", 38 | "babel-register": "^6.26.0", 39 | "coveralls": "3.0.9", 40 | "nyc": "15.0.0", 41 | "posthtml": "0.12.0", 42 | "standard": "14.3.1" 43 | }, 44 | "keywords": [ 45 | "HTML", 46 | "HTMLHINT", 47 | "PostHTML", 48 | "PostHTML Hint" 49 | ], 50 | "author": { 51 | "name": "Michael Ciniawky", 52 | "email": "michael.ciniawsky@gmail.com" 53 | }, 54 | "repository": { 55 | "type": "git", 56 | "url": "https://github.com/posthtml/posthtml-hint" 57 | }, 58 | "bugs": { 59 | "url": "https://github.com/posthtml/posthtml-hint/issues" 60 | }, 61 | "homepage": "https://github.com/posthtml/posthtml-hint#readme", 62 | "license": "MIT" 63 | } 64 | -------------------------------------------------------------------------------- /test/expect/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PostHTML | Hint 6 | 7 | 8 | 9 |

/h1> 10 |

11 |

12 |
13 |

14 | 15 | -------------------------------------------------------------------------------- /test/fixtures/.htmlhintrc: -------------------------------------------------------------------------------- 1 | { 2 | "tag-pair": true, 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PostHTML | Hint 6 | 7 | 8 | 9 |

/h1> 10 |

11 |

12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | // ------------------------------------ 2 | // #POSTHTML - HINT - TEST 3 | // ------------------------------------ 4 | 5 | 'use strict' 6 | 7 | const posthtml = require('posthtml') 8 | const test = require('ava') 9 | const path = require('path') 10 | const plugin = require('../') 11 | 12 | const fs = require('fs') 13 | 14 | async function run () { 15 | return new Promise((resolve, reject) => { 16 | const html = fs.readFileSync(path.join(__dirname, 'fixtures', 'index.html'), 'utf8') 17 | posthtml([plugin(path.join(__dirname, 'fixtures', '.htmlhintrc'))]).process(html).then(resolve, reject) 18 | }) 19 | } 20 | 21 | test('should lint HTML and error as expected', async (t) => { 22 | const result = await run() 23 | const html = fs.readFileSync(path.join(__dirname, 'expect', 'index.html'), 'utf8') 24 | t.is(result.html, html) 25 | }) 26 | -------------------------------------------------------------------------------- /test/lib/line.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const chalk = require('chalk') 3 | 4 | const line = require('../../lib/line') 5 | 6 | test('line and column default to zero', t => { 7 | const res = line() 8 | const expect = chalk.white('[0:0]') 9 | t.is(res, expect) 10 | }) 11 | -------------------------------------------------------------------------------- /test/lib/msg.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const chalk = require('chalk') 3 | 4 | const msg = require('../../lib/msg') 5 | 6 | test('should transform msgs', t => { 7 | const res = msg('test') 8 | const expect = chalk.white('test') 9 | 10 | t.is(res, expect) 11 | }) 12 | 13 | const longMsg = 'lorem ipsum dolor sit amet.' 14 | 15 | test('should split long msgs', t => { 16 | const res = msg([longMsg, longMsg, longMsg, longMsg].join(' ')) 17 | const expect = chalk.white('lorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet.\nlorem ipsum dolor sit amet.') 18 | 19 | t.is(res, expect) 20 | }) 21 | 22 | test('should split longer msgs', t => { 23 | const res = msg([longMsg, longMsg, longMsg, longMsg, longMsg, longMsg, longMsg, longMsg, longMsg, longMsg, longMsg, longMsg, longMsg].join(' ')) 24 | 25 | const expect = chalk.white('lorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet.\nlorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet.\nlorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet. lorem ipsum dolor sit amet.') 26 | 27 | t.is(res, expect) 28 | }) 29 | -------------------------------------------------------------------------------- /test/lib/title.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const chalk = require('chalk') 3 | 4 | const { transform } = require('../../lib/title') 5 | 6 | test('should transform titles', t => { 7 | const res = transform('test') 8 | const expect = chalk.white('test') 9 | t.is(res, expect) 10 | }) 11 | -------------------------------------------------------------------------------- /test/lib/type.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const chalk = require('chalk') 3 | 4 | const types = require('../../lib/type') 5 | 6 | test('should log errors in red', t => { 7 | const res = types('test') 8 | t.is(res, chalk.white('✖ test')) 9 | }) 10 | --------------------------------------------------------------------------------