├── .gitignore ├── .travis.yml ├── README.md ├── index.js ├── license ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | Thumbs.db 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'iojs' 4 | - '4' 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # trunc-html 2 | 3 | [![Build Status](https://travis-ci.org/bevacqua/trunc-html.svg?branch=master)](https://travis-ci.org/bevacqua/trunc-html) 4 | 5 | > truncate html by text length 6 | 7 | # install 8 | 9 | using `npm`. 10 | 11 | ```shell 12 | npm install -S trunc-html 13 | ``` 14 | 15 | # features 16 | 17 | - fast, lean, extensible 18 | - truncate by text length, not html length 19 | - truncate by complete words, not just by characters 20 | 21 | # `trunc(html, limit, options?)` 22 | 23 | Returns the result of truncating the provided `html`. A plain-text version is provided as well. 24 | 25 | ```js 26 | var html = 'the force is with this one. some more rubbish'; 27 | trunc(html, 30); 28 | // <- 29 | // { html: 'the force is with this one. …', 30 | // text: 'the force is with this one. …' } 31 | ``` 32 | 33 | ## `limit` 34 | 35 | Maximum amount of text characters allowed. When the `limit` is reached, the algorithm will trace back to the last word separator and trim the rest into a `…` glyph. 36 | 37 | ## `options.ignoreTags` 38 | 39 | If you'd like to supress certain HTML tags from being output you can provide an array of tags to be excluded, set `ignoreTags` to something like `['strong']`. 40 | 41 | ## `options.imageAltText` 42 | 43 | If you'd like to use the `alt` attribute for the text portion of the result, instead of dropping images entirely in text flavor, set `imageAltText` to `true`. 44 | 45 | ## `options.sanitizer` 46 | 47 | Options passed to [`insane`][1]. Note that these options are overridden by the options provided by `trunc-html`, so you can't use `transformText`, which `trunc-html` reserves for itself. 48 | 49 | # related 50 | 51 | - [`trunc-text`](https://github.com/bevacqua/trunc-text) 52 | 53 | # license 54 | 55 | MIT 56 | 57 | [1]: http://github.com/bevacqua/insane 58 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var insane = require('insane'); 4 | var assign = require('assignment'); 5 | var truncText = require('trunc-text'); 6 | var delimiter = '…'; 7 | 8 | function intoHashMap (map, tag) { 9 | map[tag] = true; 10 | return map; 11 | } 12 | 13 | function truncHtml (input, limit, options) { 14 | var o = options || {}; 15 | var remainder = Number(limit); 16 | var ignoreTags = (o.ignoreTags || []).reduce(intoHashMap, Object.create(null)); 17 | var altBuffer = ''; 18 | var plain = ''; 19 | var insaneDefaults = { 20 | filter: filter, 21 | transformText: transformText 22 | }; 23 | var sanitizer = o.sanitizer || {}; 24 | var opts = assign({}, sanitizer, insaneDefaults); 25 | var html = insane(input, opts); 26 | return { html: html, text: plain + altBuffer }; 27 | function filter (token) { 28 | if (token.tag in ignoreTags) { 29 | return false; 30 | } 31 | if (remainder <= 0) { 32 | return false; 33 | } 34 | if (sanitizer.filter && !sanitizer.filter(token)) { 35 | return false; 36 | } 37 | if (o.imageAltText && token.tag === 'img') { 38 | altBuffer += token.attrs.alt; 39 | } 40 | return true; 41 | } 42 | function transformText (text) { 43 | if (remainder <= 0) { 44 | return ''; 45 | } 46 | var truncated = truncText(text, remainder); 47 | if (truncated[truncated.length - 1] === delimiter) { 48 | remainder = 0; 49 | } else { 50 | remainder -= truncated.length; 51 | } 52 | plain += altBuffer + truncated; 53 | altBuffer = ''; 54 | return truncated; 55 | } 56 | } 57 | 58 | module.exports = truncHtml; 59 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2016 Nicolas Bevacqua 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trunc-html", 3 | "description": "truncate html by text length", 4 | "version": "1.1.2", 5 | "homepage": "https://github.com/bevacqua/trunc-html", 6 | "author": { 7 | "name": "Nicolás Bevacqua", 8 | "email": "hello@ponyfoo.com", 9 | "url": "https://ponyfoo.com" 10 | }, 11 | "license": "MIT", 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/bevacqua/trunc-html.git" 15 | }, 16 | "scripts": { 17 | "test": "ava" 18 | }, 19 | "dependencies": { 20 | "assignment": "2.2.0", 21 | "insane": "2.6.1", 22 | "trunc-text": "1.0.1" 23 | }, 24 | "devDependencies": { 25 | "ava": "0.11.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var test = require('ava'); 2 | var trunc = require('./'); 3 | var sw = 'the force is with this one. some more rubbish'; 4 | 5 | test(t => { 6 | t.same(trunc(sw, 30), { 7 | html: 'the force is with this one. …', 8 | text: 'the force is with this one. …' 9 | }); 10 | }); 11 | 12 | test(t => { 13 | t.same(trunc(sw, 30, { ignoreTags: ['strong'] }), { 14 | html: 'the force is . some more …', 15 | text: 'the force is . some more …' 16 | }); 17 | }); 18 | 19 | test(t => { 20 | t.same(trunc(sw, 30, { sanitizer: { allowedTags: [] } }), { 21 | html: 'the force is . some more …', 22 | text: 'the force is . some more …' 23 | }); 24 | }); 25 | 26 | 27 | test(t => { 28 | t.same(trunc('some sort of tada 🎉', 30, { imageAltText: true }), { 29 | html: 'some sort of tada 🎉', 30 | text: 'some sort of tada 🎉' 31 | }); 32 | t.same(trunc('some 🎉 sort of tada 🎉', 30, { imageAltText: true }), { 33 | html: 'some 🎉 sort of tada 🎉', 34 | text: 'some 🎉 sort of tada 🎉' 35 | }); 36 | t.same(trunc('some sort of tada 🎉 then bar scoop', 30, { imageAltText: true, sanitizer: { filter: token => token.tag !== 'img' || token.attrs.class === 'tj-emoji' } }), { 37 | html: 'some sort of tada 🎉 then scoop', 38 | text: 'some sort of tada 🎉 then scoop' 39 | }); 40 | }); 41 | --------------------------------------------------------------------------------