├── logos ├── logo-box-builtby.png └── logo-box-madefor.png ├── .gitignore ├── package.json ├── LICENSE.md ├── tests └── test.js ├── README.md └── index.js /logos/logo-box-builtby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apostrophecms/split-html/main/logos/logo-box-builtby.png -------------------------------------------------------------------------------- /logos/logo-box-madefor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apostrophecms/split-html/main/logos/logo-box-madefor.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /package-lock.json 2 | npm-debug.log 3 | *.DS_Store 4 | /node_modules 5 | # We do not commit CSS, only LESS 6 | /public/css/*.css 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "split-html", 3 | "version": "1.1.0", 4 | "description": "Split HTML into two valid fragments wherever a certain selector is matched. Works on the server side.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha tests/test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/apostrophecms/split-html" 12 | }, 13 | "keywords": [ 14 | "html", 15 | "split", 16 | "split html", 17 | "fragments", 18 | "html fragments", 19 | "dom" 20 | ], 21 | "author": "Apostrophe Technologies, Inc", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/apostrophecms/split-html/issues" 25 | }, 26 | "homepage": "https://github.com/apostrophecms/split-html", 27 | "dependencies": { 28 | "cheerio": "^0.22.0" 29 | }, 30 | "devDependencies": { 31 | "mocha": "^10.2.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 P'unk Avenue LLC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | var assert = require("assert"); 2 | var splitHtml = require("../index.js"); 3 | describe('splitHtml', function(){ 4 | it('Leaves img-free HTML alone when splitting on img', function() { 5 | var html = '
This is fun.
Loose text.'; 6 | var result = splitHtml(html, 'img'); 7 | assert(result.length === 1); 8 | assert(result[0] === html); 9 | }); 10 | it('Splits into the correct three components in the presence of img', function() { 11 | var html = '
Second component.
'; 12 | var result = splitHtml(html, 'img'); 13 | assert(result.length === 3); 14 | assert(result[0] === '
');
16 | assert(result[2] === 'Second component.
'); 17 | }); 18 | it('Correctly closes open tags in the first component and reopens them at the start of the second component', function() { 19 | var html = '
Second component.
'; 20 | var result = splitHtml(html, 'img'); 21 | assert(result.length === 3); 22 | assert(result[0] === '
');
24 | assert(result[2] === 'Second component.
'); 25 | }); 26 | it('Works with free text', function() { 27 | var html = 'Text one
Text two';
28 | var result = splitHtml(html, 'img');
29 | assert(result.length === 3);
30 | assert(result[0] === 'Text one');
31 | assert(result[1] === '
');
32 | assert(result[2] === 'Text two');
33 | });
34 | it('Works with multiple instances', function() {
35 | var html = '
Second component.

Third component.
'; 36 | var result = splitHtml(html, 'img'); 37 | assert(result.length === 5); 38 | assert(result[0] === '
');
40 | assert(result[2] === 'Second component.
'); 41 | assert(result[3] === '
');
42 | assert(result[4] === 'Third component.
'); 43 | }); 44 | it('Respects test function', function() { 45 | var html = '
Second component.
Link text.More text in second component.
'; 46 | var result = splitHtml(html, 'a', function($el) { 47 | if ($el.find('img').length) { 48 | return true; 49 | } else { 50 | return false; 51 | } 52 | }); 53 | assert(result.length === 3); 54 | assert(result[0] === '
');
56 | assert(result[2] === 'Second component.
Link text.More text in second component.
'); 57 | }); 58 | it('Respects a split at the end of a word', function() { 59 | var html = 'One
Two
Three
Four
'; 60 | var result = splitHtml(html, 'span[data-split-marker]'); 61 | assert(result.length === 3); 62 | assert(result[0] === 'One
Two
'); 63 | assert(result[1] === ''); 64 | assert(result[2] === 'Three
Four
'); 65 | }); 66 | it('Splits properly when parents are multiple levels deep', function() { 67 | var html = 'Hello!Goodbye.
Hello!
Goodbye.
5 |
6 | Given a string containing an HTML fragment, split that string into two or more **correctly balanced** HTML fragments wherever the specified selector is found. Returns both the new fragments and the elements that matched the selector, in alternation. **Works on the server and in the browser.** Powered by Cheerio on the server side, jQuery in the browser.
7 |
8 | ```javascript
9 | var splitHtml = require('split-html');
10 | var html = '
' +
13 | 'Second component.
' + 14 | '
',
25 | 'Second component.
79 |
80 | ## Changelog
81 |
82 | ### 1.1.0 - 2020-09-09
83 |
84 | * Adds the Cheerio configuration option in a fourth options argument.
85 |
86 | ### CHANGES IN 1.0.3
87 |
88 | * Included an explicit LICENSE.md file (no change, still MIT licensed). No changes in functionality.
89 |
90 | ### CHANGES IN 1.0.2
91 |
92 | * Undeclared variable fixed. No functional changes.
93 |
94 | ### CHANGES IN 1.0.1
95 |
96 | * Clarified that this code is mature for browser use as well. No code changes.
97 |
98 | ### CHANGES IN 1.0.0
99 |
100 | * Updated documentation and released 1.0.0 stable. No code changes.
101 |
102 | ### CHANGES IN 0.1.1
103 |
104 | * Works correctly with actual jQuery, in addition to working correctly in node with Cheerio as before. This required changes to be more pedantic about closing parent tags in the first fragment, and a better simulation of Cheerio's document object.
105 | * Handles nested parent elements correctly.
106 |
107 | ### CHANGES IN 0.1.0
108 |
109 | Initial release. With shiny unit tests, of course.
110 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var cheerio;
3 | if (typeof window === 'undefined') {
4 | // node
5 | module.exports = splitHtml;
6 | cheerio = require('cheerio');
7 | } else {
8 | window.splitHtml = splitHtml;
9 | // In the browser, use actual jQuery in place of Cheerio.
10 | // Create a simulated cheerio object.
11 | cheerio = {
12 | load: function(html) {
13 | var $wrapper = jQuery('