| example/* linguist-documentation |
+10
| notifications: | ||
| email: false | ||
| language: node_js | ||
| node_js: | ||
| - 'node' | ||
| script: | ||
| - yarn lint |
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>line-clamp</title> | ||
| <meta charset="utf-8"> | ||
| <style> | ||
| .line-clamp { | ||
| width: 100px; | ||
| line-height: 20px; | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <div class="line-clamp"> | ||
| Lorem ipsum dolor sit amet, <strong>consectetur adipiscing</strong> elit. | ||
| </div> | ||
| <script src="/bundle.js"></script> | ||
| <script> | ||
| const element = document.querySelector('.line-clamp') | ||
| lineClamp(element, 3) | ||
| </script> | ||
| </body> | ||
| </html> |
+116
| function truncateTextNode ( | ||
| textNode, | ||
| rootElement, | ||
| maximumHeight, | ||
| ellipsisCharacter | ||
| ) { | ||
| truncateTextNodeByWord( | ||
| textNode, | ||
| rootElement, | ||
| maximumHeight, | ||
| ellipsisCharacter | ||
| ) | ||
| return truncateTextNodeByCharacter( | ||
| textNode, | ||
| rootElement, | ||
| maximumHeight, | ||
| ellipsisCharacter | ||
| ) | ||
| } | ||
| function truncateTextNodeByWord (textNode, rootElement, maximumHeight) { | ||
| var lastIndexOfWhitespace | ||
| var textContent = textNode.textContent | ||
| while (textContent.length > 1) { | ||
| lastIndexOfWhitespace = textContent.lastIndexOf(' ') | ||
| if (lastIndexOfWhitespace == -1) { | ||
| return | ||
| } | ||
| textNode.textContent = textContent.substring(0, lastIndexOfWhitespace) | ||
| if (rootElement.scrollHeight <= maximumHeight) { | ||
| textNode.textContent = textContent | ||
| return | ||
| } | ||
| textContent = textNode.textContent | ||
| } | ||
| } | ||
| var TRAILING_WHITESPACE_AND_PUNCTUATION_REGEX = /[ .,;!?'‘’“”\-–—]+$/ | ||
| function truncateTextNodeByCharacter ( | ||
| textNode, | ||
| rootElement, | ||
| maximumHeight, | ||
| ellipsisCharacter | ||
| ) { | ||
| var textContent = textNode.textContent | ||
| var length = textContent.length | ||
| while (length > 1) { | ||
| // Trim off one trailing character and any trailing punctuation and whitespace. | ||
| textContent = textContent | ||
| .substring(0, length - 1) | ||
| .replace(TRAILING_WHITESPACE_AND_PUNCTUATION_REGEX, '') | ||
| length = textContent.length | ||
| textNode.textContent = textContent + ellipsisCharacter | ||
| if (rootElement.scrollHeight <= maximumHeight) { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } | ||
| function truncateElementNode ( | ||
| element, | ||
| rootElement, | ||
| maximumHeight, | ||
| ellipsisCharacter | ||
| ) { | ||
| var childNodes = element.childNodes | ||
| var i = childNodes.length - 1 | ||
| while (i > -1) { | ||
| var childNode = childNodes[i--] | ||
| var nodeType = childNode.nodeType | ||
| if ( | ||
| (nodeType == 1 && | ||
| truncateElementNode( | ||
| childNode, | ||
| rootElement, | ||
| maximumHeight, | ||
| ellipsisCharacter | ||
| )) || | ||
| (nodeType == 3 && | ||
| truncateTextNode( | ||
| childNode, | ||
| rootElement, | ||
| maximumHeight, | ||
| ellipsisCharacter | ||
| )) | ||
| ) { | ||
| return true | ||
| } | ||
| element.removeChild(childNode) | ||
| } | ||
| return false | ||
| } | ||
| var ELLIPSIS_CHARACTER = '\u2026' | ||
| module.exports = function (rootElement, lineCount, options) { | ||
| rootElement.style.cssText += | ||
| 'overflow:hidden;overflow-wrap:break-word;word-wrap:break-word' | ||
| var maximumHeight = | ||
| (lineCount || 1) * | ||
| parseInt(window.getComputedStyle(rootElement).lineHeight, 10) | ||
| // Exit if text does not overflow `rootElement`. | ||
| if (rootElement.scrollHeight <= maximumHeight) { | ||
| return | ||
| } | ||
| truncateElementNode( | ||
| rootElement, | ||
| rootElement, | ||
| maximumHeight, | ||
| (options && options.ellipsis) || ELLIPSIS_CHARACTER | ||
| ) | ||
| } |
Sorry, the diff of this file is too big to display
+1
-1
| The MIT License (MIT) | ||
| Copyright (c) 2016 Lim Yuan Qing | ||
| Copyright (c) 2018 Lim Yuan Qing | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
+12
-30
| { | ||
| "name": "line-clamp", | ||
| "version": "0.0.4", | ||
| "description": "Truncate multi-line text in a DOM element.", | ||
| "version": "0.0.5", | ||
| "description": "Line clamp a DOM element in vanilla JavaScript.", | ||
| "author": "Lim Yuan Qing", | ||
| "license": "MIT", | ||
| "main": "lib/index.js", | ||
| "repository": { | ||
@@ -12,32 +11,15 @@ "type": "git", | ||
| }, | ||
| "files": [ | ||
| "lib", | ||
| "src" | ||
| ], | ||
| "devDependencies": { | ||
| "babel-core": "6.7.2", | ||
| "babel-eslint": "5.0.0", | ||
| "babel-preset-es2015": "6.6.0", | ||
| "babelify": "7.2.0", | ||
| "browserify": "13.0.0", | ||
| "del": "2.2.0", | ||
| "ecstatic": "1.4.0", | ||
| "gulp": "3.9.1", | ||
| "gulp-babel": "6.1.2", | ||
| "gulp-eslint": "1.1.1", | ||
| "gulp-util": "3.0.7", | ||
| "nopt": "3.0.6", | ||
| "opn": "4.0.1", | ||
| "require-dir": "0.3.0", | ||
| "run-sequence": "1.1.5", | ||
| "tape": "4.5.1", | ||
| "vinyl-buffer": "1.0.0", | ||
| "vinyl-source-stream": "1.1.0", | ||
| "watchify": "3.7.0" | ||
| "concurrently": "^3.5.1", | ||
| "ecstatic": "^3.2.0", | ||
| "gzip-size-cli": "^2.1.0", | ||
| "opn-cli": "^3.1.0", | ||
| "prettier-standard": "^8.0.0", | ||
| "uglify-js": "^3.3.11", | ||
| "watchify": "^3.10.0" | ||
| }, | ||
| "scripts": { | ||
| "example": "gulp example", | ||
| "lint": "gulp lint", | ||
| "prepublish": "gulp build", | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
| "start": "concurrently \"watchify index.js --standalone lineClamp --outfile example/bundle.js\" \"ecstatic example --port 8080\" \"opn 'http://0.0.0.0:8080/'\"", | ||
| "lint": "prettier-standard index.js test/index.js --no-semi --single-quote --write", | ||
| "weight": "uglifyjs index.js --compress --mangle --toplevel | gzip-size" | ||
| }, | ||
@@ -44,0 +26,0 @@ "keywords": [ |
+36
-45
| # line-clamp [](https://www.npmjs.com/package/line-clamp) [](https://travis-ci.org/yuanqing/line-clamp) | ||
| > Truncate multi-line text in a DOM element. | ||
| > Line clamp a DOM element in vanilla JavaScript. | ||
| ## Features | ||
| - Pure JavaScript; does *not* use [`-webkit-line-clamp`](https://css-tricks.com/line-clampin/) | ||
| - Works even if the given element contains nested DOM nodes | ||
| - Supports appending a custom string instead of an ellipsis | ||
| - Exit if we detect that no truncation is necessary (ie. content does not overflow the element) | ||
| - Exit if we detect that no truncation is necessary (ie. content does not overflow container). | ||
| - Allows use of a custom string instead of an ellipsis. | ||
| ## Usage | ||
| ## Limitations | ||
| > [**Editable demo (CodePen)**](https://codepen.io/lyuanqing/pen/VQQVry) | ||
| - Requires some [CSS to be set on the DOM element and its parent](#css). In particular, the DOM element must have an explicitly set `line-height` in pixels. | ||
| - Truncation is in pure JavaScript; does *not* use [`-webkit-line-clamp`](https://css-tricks.com/line-clampin/). | ||
| - Assumes that the text to be truncated does *not* contain any inline HTML tags (eg. `em`, `strong`, etc.). | ||
| HTML: | ||
| ## Usage | ||
| #### HTML | ||
| ```html | ||
| <div class="line-clamp-wrapper"> | ||
| <div class="line-clamp">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div> | ||
| <div class="line-clamp"> | ||
| Lorem ipsum dolor sit amet, <strong>consectetur adipiscing</strong> elit. | ||
| </div> | ||
| ``` | ||
| #### CSS | ||
| CSS: | ||
| ```css | ||
| .line-clamp-wrapper { | ||
| height: 60px; | ||
| overflow: hidden; | ||
| } | ||
| .line-clamp { | ||
| width: 100px; | ||
| line-height: 20px; | ||
| overflow-wrap: break-word; | ||
| word-wrap: break-word; | ||
| } | ||
| ``` | ||
| #### JavaScript | ||
| JavaScript: | ||
| ```js | ||
| import lineClamp from 'line-clamp'; | ||
| const element = document.querySelector('.line-clamp') | ||
| lineClamp(element, 3) | ||
| ``` | ||
| lineClamp(element, { lineCount: 3 }); | ||
| Boom: | ||
| ```html | ||
| <div class="line-clamp" style="overflow: hidden; overflow-wrap: break-word; word-wrap: break-word;"> | ||
| Lorem ipsum dolor sit amet, <strong>consectetur…</strong> | ||
| </div> | ||
| ``` | ||
| ## Example | ||
| ### Limitations | ||
| To run the [example](example), do: | ||
| - The element is assumed to have a pixel line-height, obtained via [`window.getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle). | ||
| ``` | ||
| $ git clone https://github.com/yuanqing/line-clamp | ||
| $ npm install | ||
| $ npm install --global gulp | ||
| $ gulp example --open | ||
| ``` | ||
| ## API | ||
| ```js | ||
| import lineClamp from 'line-clamp'; | ||
| const lineClamp = require('line-clamp') | ||
| ``` | ||
| ### lineClamp(element, options) | ||
| ### lineClamp(element, lineCount [, options]) | ||
| - `element` — A DOM element. | ||
| `options` is an optional object literal. | ||
| - `options` — An object literal: | ||
| - Set `options.ellipsis` to change the string to be appended to the truncated text (defaults to `…`). | ||
| Key | Description | Default | ||
| :--|:--|:-- | ||
| `ellipsisCharacter` | The string to append to the truncated text. | `\u2026` | ||
| `lineCount` | *Required.* The number of lines to show. | `undefined` | ||
| See [Usage](#usage). | ||
| See [Usage](#usage) above for the accompanying CSS. | ||
| ## Installation | ||
| Install via [npm](https://npmjs.com): | ||
| Install via [yarn](https://yarnpkg.com): | ||
| ```sh | ||
| $ yarn add line-clamp | ||
| ``` | ||
| $ npm i --save line-clamp | ||
| Or [npm](https://npmjs.com): | ||
| ```sh | ||
| $ npm install --save line-clamp | ||
| ``` | ||
@@ -86,0 +77,0 @@ |
-79
| 'use strict'; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.default = function (element) { | ||
| var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, | ||
| lineCount = _ref.lineCount, | ||
| ellipsisCharacter = _ref.ellipsisCharacter; | ||
| // Read the `line-height` of `element`, and use it to compute the height of | ||
| // `element` required to fit the given `lineCount`. | ||
| var lineHeight = parseInt(window.getComputedStyle(element).lineHeight, 10); | ||
| var maximumHeight = lineCount * lineHeight; | ||
| // Exit if text does not overflow the `element`. | ||
| if (element.scrollHeight <= maximumHeight) { | ||
| return; | ||
| } | ||
| truncateByWord(element, maximumHeight); | ||
| truncateByCharacter(element, maximumHeight, ellipsisCharacter || ELLIPSIS); | ||
| }; | ||
| var ELLIPSIS = '\u2026'; | ||
| var WHITESPACE_REGEX = /(?=\s)/; | ||
| var TRAILING_WHITESPACE_REGEX = /\s+$/; | ||
| // Truncate the text of `element` such that it does not exceed the | ||
| // `maximumHeight`. Return `true` if we need to truncate by character, else | ||
| // return `false`. | ||
| function truncateByWord(element, maximumHeight) { | ||
| var innerHTML = element.innerHTML; | ||
| // Split the text of `element` by whitespace. | ||
| var chunks = innerHTML.split(WHITESPACE_REGEX); | ||
| // The text does not contain whitespace; we need to attempt to truncate | ||
| // by character. | ||
| if (chunks.length === 1) { | ||
| return true; | ||
| } | ||
| // Loop over the chunks, and try to fit more chunks into the `element`. | ||
| var i = -1; | ||
| var length = chunks.length; | ||
| var newInnerHTML = ''; | ||
| while (++i < length) { | ||
| newInnerHTML += chunks[i]; | ||
| element.innerHTML = newInnerHTML; | ||
| // If the new height now exceeds the `maximumHeight` (where it did not | ||
| // in the previous iteration), we know that we are at most one line | ||
| // over the optimal text length. | ||
| if (element.offsetHeight > maximumHeight) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| // Append `ellipsisCharacter` to `element`, trimming off trailing characters | ||
| // in `element` such that `element` will not exceed the `maximumHeight`. | ||
| function truncateByCharacter(element, maximumHeight, ellipsisCharacter) { | ||
| var innerHTML = element.innerHTML; | ||
| var length = innerHTML.length; | ||
| // In each iteration, we trim off one trailing character . Also trim | ||
| // off any trailing punctuation before appending the `ellipsisCharacter`. | ||
| while (length > 0) { | ||
| element.innerHTML = innerHTML.substring(0, length).replace(TRAILING_WHITESPACE_REGEX, '') + ellipsisCharacter; | ||
| if (element.offsetHeight <= maximumHeight) { | ||
| return; | ||
| } | ||
| length--; | ||
| } | ||
| } |
-70
| const ELLIPSIS = '\u2026'; | ||
| const WHITESPACE_REGEX = /(?=\s)/; | ||
| const TRAILING_WHITESPACE_REGEX = /\s+$/; | ||
| // Truncate the text of `element` such that it does not exceed the | ||
| // `maximumHeight`. Return `true` if we need to truncate by character, else | ||
| // return `false`. | ||
| function truncateByWord(element, maximumHeight) { | ||
| const innerHTML = element.innerHTML; | ||
| // Split the text of `element` by whitespace. | ||
| let chunks = innerHTML.split(WHITESPACE_REGEX); | ||
| // The text does not contain whitespace; we need to attempt to truncate | ||
| // by character. | ||
| if (chunks.length === 1) { | ||
| return true; | ||
| } | ||
| // Loop over the chunks, and try to fit more chunks into the `element`. | ||
| let i = -1; | ||
| const length = chunks.length; | ||
| let newInnerHTML = ''; | ||
| while (++i < length) { | ||
| newInnerHTML += chunks[i]; | ||
| element.innerHTML = newInnerHTML; | ||
| // If the new height now exceeds the `maximumHeight` (where it did not | ||
| // in the previous iteration), we know that we are at most one line | ||
| // over the optimal text length. | ||
| if (element.offsetHeight > maximumHeight) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| // Append `ellipsisCharacter` to `element`, trimming off trailing characters | ||
| // in `element` such that `element` will not exceed the `maximumHeight`. | ||
| function truncateByCharacter(element, maximumHeight, ellipsisCharacter) { | ||
| const innerHTML = element.innerHTML; | ||
| let length = innerHTML.length; | ||
| // In each iteration, we trim off one trailing character . Also trim | ||
| // off any trailing punctuation before appending the `ellipsisCharacter`. | ||
| while (length > 0) { | ||
| element.innerHTML = innerHTML.substring(0, length).replace(TRAILING_WHITESPACE_REGEX, '') + ellipsisCharacter; | ||
| if (element.offsetHeight <= maximumHeight) { | ||
| return; | ||
| } | ||
| length--; | ||
| } | ||
| } | ||
| export default function(element, { lineCount, ellipsisCharacter } = {}) { | ||
| // Read the `line-height` of `element`, and use it to compute the height of | ||
| // `element` required to fit the given `lineCount`. | ||
| const lineHeight = parseInt(window.getComputedStyle(element).lineHeight, 10); | ||
| const maximumHeight = lineCount * lineHeight; | ||
| // Exit if text does not overflow the `element`. | ||
| if (element.scrollHeight <= maximumHeight) { | ||
| return; | ||
| } | ||
| truncateByWord(element, maximumHeight); | ||
| truncateByCharacter(element, maximumHeight, ellipsisCharacter || ELLIPSIS); | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
113737
1117.74%7
-63.16%8
60%2
-33.33%108
-11.48%86
-9.47%1
Infinity%1
Infinity%