├── .github └── workflows │ └── node.js.yml ├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── jsconfig.json ├── package-lock.json ├── package.json └── test.js /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [master] 9 | pull_request: 10 | branches: [master] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [18, 20, 22] 19 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | cache: npm 28 | - run: npm ci 29 | - run: npm run build --if-present 30 | - run: npm test 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.d.ts 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Mohamed Akram 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 | # html-format 2 | 3 | Format HTML strings by indenting, wrapping, and removing unnecessary 4 | whitespace while preserving newlines. 5 | 6 | ## Install 7 | 8 | npm install html-format 9 | 10 | ## Usage 11 | 12 | ```javascript 13 | import format from "html-format"; 14 | 15 | const html = `\ 16 |
17 |\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
", 130 | "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua.
" 131 | ); 132 | 133 | test( 134 | "Wrap long tag", 135 | 'Go', 136 | 'Go' 137 | ); 138 | 139 | test( 140 | "Wrap after special element", 141 | "this is an incredibly long sentence that never seems to endthis should actually wrap", 142 | "
this is an incredibly long sentence that never seems to endthis\nshould actually wrap" 143 | ); 144 | 145 | test( 146 | "Do not wrap after special element", 147 | "
this is an incredibly long sentence that never seems to end\n starting a new paragraphthis should not actually wrap", 148 | "
this is an incredibly long sentence that never seems to end\n starting a new paragraphthis should not actually wrap" 149 | ); 150 | 151 | test( 152 | "Do not format pre element content", 153 | '
\ns p a c es', 154 | '
\ns p a c es' 155 | ); 156 | 157 | test( 158 | "Do not format textarea element content", 159 | ' s', 160 | ' s' 161 | ); 162 | 163 | test( 164 | "Do not format style element content", 165 | "", 166 | "" 167 | ); 168 | 169 | test( 170 | "Do not format script element content", 171 | '', 172 | '' 173 | ); 174 | 175 | test( 176 | "Format special tag attributes", 177 | '', 178 | '' 179 | ); 180 | 181 | test( 182 | "Wrap special tag", 183 | '', 184 | '' 185 | ); 186 | 187 | test( 188 | "Do not indent after doctype", 189 | "\n", 190 | "\n" 191 | ); 192 | 193 | test( 194 | "Do not indent after comment", 195 | "\n", 196 | "\n" 197 | ); 198 | 199 | test( 200 | "Do not parse tags inside quotes", 201 | '
do not remove me", 289 | "do not remove me" 290 | ); 291 | 292 | test( 293 | "Handle invalid HTML", 294 | "< this is a very long sentence to test the regex", 295 | "< this is a very long sentence to test the regex", 296 | false 297 | ); 298 | 299 | test("Void tags work correctly", "
\n
", "
\n
"); 300 | 301 | test( 302 | "Handle self-closing tag", 303 | "\n ", 304 | " \n " 305 | ); 306 | 307 | test("Handle extraneous slashes 1", " ", " ", false); 308 | test("Handle extraneous slashes 2", " ", " ", false); 309 | 310 | test( 311 | "Handle arbitrary text in tag", 312 | ' \nstuff\n', 313 | '\n stuff\n', 314 | false 315 | ); 316 | --------------------------------------------------------------------------------