{"id":25445828,"url":"https://github.com/rkotze/joinable","last_synced_at":"2025-11-01T21:30:34.085Z","repository":{"id":57281474,"uuid":"63529533","full_name":"rkotze/joinable","owner":"rkotze","description":"Join strings with built in control flow and handle separator","archived":false,"fork":false,"pushed_at":"2018-10-02T20:23:19.000Z","size":52,"stargazers_count":25,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-18T20:08:00.286Z","etag":null,"topics":["classnames","falsy","join-strings","reactjs","repetitive-checks"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/joinable","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/rkotze.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-07-17T11:54:54.000Z","updated_at":"2023-03-09T01:56:47.000Z","dependencies_parsed_at":"2022-09-19T22:02:19.593Z","dependency_job_id":null,"html_url":"https://github.com/rkotze/joinable","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkotze%2Fjoinable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkotze%2Fjoinable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkotze%2Fjoinable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkotze%2Fjoinable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rkotze","download_url":"https://codeload.github.com/rkotze/joinable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239331465,"owners_count":19621220,"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","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":["classnames","falsy","join-strings","reactjs","repetitive-checks"],"created_at":"2025-02-17T16:50:32.264Z","updated_at":"2025-11-01T21:30:33.986Z","avatar_url":"https://github.com/rkotze.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Joinable\n\n[![Version](http://img.shields.io/npm/v/joinable.svg)](https://www.npmjs.org/package/joinable)\n[![Build Status](https://travis-ci.org/rkotze/joinable.svg?branch=master)](https://travis-ci.org/rkotze/joinable)\n\nJoin strings easily by removing the repetitive `falsy` checks. Construct strings like form validation, CSS classes, URLs and more.\n\n## Usage\n\n`npm install joinable`\n\n```javascript\nimport joinable from \"joinable\";\njoinable(\"potato\", undefined, \"rice\"); // =\u003e 'potato rice'\n```\n\n## About\n\n**What is Joinable:** A library to join strings together without the need to check if a value is a falsy like `undefined`.\n\n**Why use Joinable:** Keep your code base clean by removing the repetitive `falsy` checks and improve the readability.\n\n**More information** about [**Joinable**](http://www.richardkotze.com/projects/joinable)\n\nHandle falsy `false, 0, \"\", undefined, null, NaN`\n\n## API\n\n`joinable` is the default export and an alias of `joinStrings`.\n\n```\njoinable(...joinables [, options]) : string\n```\n\n```JavaScript\nimport joinable from 'joinable';\njoinable('potato', undefined, 'rice', null, 'carrot'); // =\u003e 'potato rice carrot'\n\n// Change separator\njoinable('potato', 'rice', 'carrot', {separator: ','}); // =\u003e 'potato,rice,carrot'\n```\n\nJoin strings based on another value like a boolean.\n\n```JavaScript\nimport joinable from 'joinable';\njoinable('potato', [true, 'spinach']); // =\u003e 'potato spinach'\njoinable('potato', [false, 'spinach']); // =\u003e 'potato'\njoinable('potato', [null, 'spinach']); // =\u003e 'potato'\n```\n\nHave a default value if a falsy passed.\n\n```JavaScript\nimport joinable from 'joinable';\njoinable('potato', [true, 'spinach', 'beetroot']); // =\u003e 'potato spinach'\njoinable('potato', [false, 'spinach', 'beetroot']); // =\u003e 'potato beetroot'\njoinable('potato', [null, 'spinach', 'beetroot']); // =\u003e 'potato beetroot'\n```\n\n### Joining classNames in ReactJS\n\n### Problem\n\nExample of typical logic string concatenation in _ReactJS component_ with if statements. General issues: verbose, unnecessary repetitive complexity and mutation:\n\n```javascript\nimport React from \"react\";\n\nconst MyComponent = props =\u003e {\n  let myClass = \"panel \";\n  if (props.hide) myClass += \"invisible \";\n\n  if (props.hasBoarder) myClass += \"sparkleBoarder \";\n\n  if (props.className) myClass += props.className;\n\n  return \u003cdiv className={myClass}\u003e{props.children}\u003c/div\u003e;\n};\n```\n\nWhile this works fine you will probably need to repeat that similar flow for a lot of components and some will have additional complexity round it.\n\n### Solution\n\nSame component as above but lets keep it clean with `joinable`.\n\n```javascript\nimport React from \"react\";\nimport joinable from \"joinable\";\n\nconst MyComponent = props =\u003e {\n  const myClass = joinable(\n    \"potato\",\n    props.className,\n    [props.hide, \"invisible\"],\n    [props.hasBoarder, \"sparkleBoarder\"]\n  );\n  return \u003cdiv className={myClass}\u003e{props.children}\u003c/div\u003e;\n};\n```\n\n### prefixStrings\n\n```\nprefixStrings(prefix, ...joinables [, options]) : string\n```\n\n```JavaScript\nimport { prefixStrings } from 'joinable';\nprefixStrings('pre-', undefined, 'rice', null, 'carrot'); // =\u003e 'pre-rice pre-carrot'\nprefixStrings(falsy, undefined, 'rice', null, 'carrot'); // =\u003e 'rice carrot'\nprefixStrings('pre-', undefined, 'rice', null, 'carrot', {separator: ','}); // =\u003e 'pre-rice,pre-carrot'\n```\n\n### joinExp\n\n**Note:** no ifArrays can be used in joinables\n\n```\njoinExp(regexp, ...joinables [, options]) : string\n```\n\n```JavaScript\nimport { joinExp } from 'joinable';\njoinExp(/m+/, 'cucumber'); // =\u003e 'cucumber'\njoinExp(/(m|n)+/, 'cucumber', false, 'sandwich'); // =\u003e 'cucumber sandwich'\njoinExp(/r+/, 'cucumber'); // =\u003e ''\njoinExp('', 'cucumber'); // =\u003e throw Error 'First parameter should be of RegExp type'\n```\n\n### joinIf\n\n```\njoinIf(ifArray)\n```\n\n```JavaScript\nimport { joinIf } from 'joinable';\njoinIf([true, 'spinach']); // =\u003e 'spinach'\njoinIf([1==2, 'spinach']); // =\u003e null\njoinIf([1==1, 'spinach', 'broccoli']); // =\u003e 'spinach'\njoinIf([1==2, 'spinach', 'broccoli']); // =\u003e 'broccoli'\njoinIf('lettuce'); // =\u003e null\n```\n\nUseful to make joining easier to read combine both `joinable` and `joinIf`.\n\n```JavaScript\nimport joinable, { joinIf } from 'joinable';\njoinable('potato', joinIf([true, 'spinach'])) # =\u003e 'potato spinach'\n```\n\n### joinObject\n\n```\njoinObject({object} [, separator, separator]) : string\n```\n\n```JavaScript\nimport { joinObject } from 'joinable';\njoinObject({ chicken: 'burger', spare: 'ribs' }) // =\u003e 'chicken=burger\u0026spare=ribs'\njoinObject({ chicken: 'burger', spare: 'ribs' }, ',') // =\u003e 'chicken=burger,spare=ribs'\njoinObject({ chicken: 'burger', spare: 'ribs' }, ';', ',') // =\u003e 'chicken,burger;spare,ribs'\njoinObject({ salad: null, chicken: 'burger', spare: 'ribs' }, ';', ',') // =\u003e 'chicken,burger;spare,ribs'\n```\n\n## Contribute:\n\nInstall: `npm i`\n\n`npm test` - unit tests and eslint\n\n`npm run benchmark` - run performance tests\n\nThis project follows [Semantic Versioning](http://semver.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkotze%2Fjoinable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frkotze%2Fjoinable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkotze%2Fjoinable/lists"}