{"id":18561249,"url":"https://github.com/apostrophecms/split-html","last_synced_at":"2025-09-05T13:50:14.703Z","repository":{"id":21368956,"uuid":"24686257","full_name":"apostrophecms/split-html","owner":"apostrophecms","description":"Split HTML into two valid fragments wherever a certain selector is matched. Works on the server side.","archived":false,"fork":false,"pushed_at":"2023-10-03T13:29:18.000Z","size":19,"stargazers_count":36,"open_issues_count":2,"forks_count":13,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-08-22T20:32:37.788Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apostrophecms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-10-01T16:42:08.000Z","updated_at":"2024-07-01T16:25:17.000Z","dependencies_parsed_at":"2024-06-18T20:27:33.339Z","dependency_job_id":null,"html_url":"https://github.com/apostrophecms/split-html","commit_stats":{"total_commits":17,"total_committers":4,"mean_commits":4.25,"dds":"0.17647058823529416","last_synced_commit":"ecc6ad79a38d2518d36ca8d2d5ef1e05fa9f0840"},"previous_names":["punkave/split-html"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/apostrophecms/split-html","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Fsplit-html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Fsplit-html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Fsplit-html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Fsplit-html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apostrophecms","download_url":"https://codeload.github.com/apostrophecms/split-html/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Fsplit-html/sbom","scorecard":{"id":203168,"data":{"date":"2025-08-11","repo":{"name":"github.com/apostrophecms/split-html","commit":"ecc6ad79a38d2518d36ca8d2d5ef1e05fa9f0840"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":1,"reason":"Found 2/17 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":9,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/apostrophecms/.github/SECURITY.md:1","Info: Found linked content: github.com/apostrophecms/.github/SECURITY.md:1","Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy","Info: Found text in security policy: github.com/apostrophecms/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-16T23:10:43.478Z","repository_id":21368956,"created_at":"2025-08-16T23:10:43.478Z","updated_at":"2025-08-16T23:10:43.478Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273767758,"owners_count":25164464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T22:06:20.837Z","updated_at":"2025-09-05T13:50:14.574Z","avatar_url":"https://github.com/apostrophecms.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"split-html\n==========\n\n\u003ca href=\"http://apostrophenow.org/\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/punkave/split-html/master/logos/logo-box-madefor.png\" align=\"right\" /\u003e\u003c/a\u003e\n\nGiven 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.\n\n```javascript\nvar splitHtml = require('split-html');\nvar html = '\u003cdiv\u003e' +\n  '\u003ch4\u003eFirst component.\u003c/h4\u003e' +\n  '\u003cimg src=\"/test.jpg\"\u003e' +\n  '\u003cp\u003eSecond component.\u003c/p\u003e' +\n  '\u003c/div\u003e';\nvar fragments = splitHtml(html, 'img');\nconsole.log(fragments);\n```\n\nThis outputs:\n\n```javascript\n[\n  '\u003cdiv\u003e\u003ch4\u003eFirst component.\u003c/h4\u003e\u003c/div\u003e',\n  '\u003cimg src=\"/test.jpg\"\u003e',\n  '\u003cdiv\u003e\u003cp\u003eSecond component.\u003c/p\u003e\u003c/div\u003e'\n]\n```\n\nNote that the `img` itself is returned. The first element in the array is always an HTML fragment, the second is always an element that matched the selector, and so on in alternation.\n\n**Any container tags already open when the `img` tag is encountered are automatically closed at the end of the first fragment and re-opened at the start of the next one with the same attributes.**\n\n## Optional test function\n\nIf a jQuery/CSS-style selector isn't specific enough, you can pass a function as the third argument. This function is called with a Cheerio or jQuery object representing the matching element. If you want to split around this element, return `true`. Otherwise, return `false`.\n\nThis is useful because Cheerio does not currently support `:has`, and also because in some situations even `:has` might not be specific enough.\n\n```javascript\n// Split on 'a', but only if it contains 'img'\nvar result = splitHtml(html, 'a', function($el) {\n  if ($el.find('img').length) {\n    return true;\n  } else {\n    return false;\n  }\n});\n```\n\n## Additional options\n\nThe following options should be passed as the fourth argument to `splitHtml` in an object.\n\n### `cheerio`\n\nAn object of Cheerio v0.x `.load()` options, [as documented here](https://www.npmjs.com/package/cheerio/v/0.22.0). This is used when using split-html on the server when preparing the HTML fragment to parse.\n\n## Why?\n\nWe wanted to import Wordpress blog posts into the [ApostropheCMS](https://apostrophecms.com) CMS. Wordpress uses HTML to embed images and videos, while Apostrophe represents blocks of text and widgets like slideshows as separate objects in an array. `split-html` allows us to neatly slice and dice existing HTML so we can transform it into Apostrophe widgets easily.\n\n## What about errors?\n\nIf `split-html` encounters something it can't figure out, such as terrible markup, it will return the original string as the only element in the array.\n\n## Using split-html in the browser\n\n`split-html` has been coded to work with either Cheerio or actual jQuery. It will automatically just use jQuery if that is present in the browser. We use this feature in production in [ApostropheCMS](http://apostrophecms.com)'s rich text editor.\n\n## About P'unk Avenue and ApostropheCMS\n\n`split-html` was created at [P'unk Avenue](https://punkave.com) for use in many projects built with Apostrophe, an open-source content management system built on node.js. If you like `split-html` you should definitely [check out apostrophecms.com](https://apostrophecms.com).\n\n## Support\n\nFeel free to open issues on [github](http://github.com/punkave/split-html).\n\n\u003ca href=\"http://punkave.com/\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/punkave/split-html/master/logos/logo-box-builtby.png\" /\u003e\u003c/a\u003e\n\n## Changelog\n\n### 1.1.0 - 2020-09-09\n\n* Adds the Cheerio configuration option in a fourth options argument.\n\n### CHANGES IN 1.0.3\n\n* Included an explicit LICENSE.md file (no change, still MIT licensed). No changes in functionality.\n\n### CHANGES IN 1.0.2\n\n* Undeclared variable fixed. No functional changes.\n\n### CHANGES IN 1.0.1\n\n* Clarified that this code is mature for browser use as well. No code changes.\n\n### CHANGES IN 1.0.0\n\n* Updated documentation and released 1.0.0 stable. No code changes.\n\n### CHANGES IN 0.1.1\n\n* 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.\n* Handles nested parent elements correctly.\n\n### CHANGES IN 0.1.0\n\nInitial release. With shiny unit tests, of course.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapostrophecms%2Fsplit-html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapostrophecms%2Fsplit-html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapostrophecms%2Fsplit-html/lists"}