{"id":15287791,"url":"https://github.com/af/jsnox","last_synced_at":"2025-10-07T02:31:50.705Z","repository":{"id":24169263,"uuid":"27559625","full_name":"af/JSnoX","owner":"af","description":"A concise, expressive way to build React DOM in pure JavaScript.","archived":true,"fork":false,"pushed_at":"2016-05-02T13:40:40.000Z","size":110,"stargazers_count":230,"open_issues_count":0,"forks_count":8,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-01-15T22:31:49.856Z","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/af.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":"2014-12-04T20:55:10.000Z","updated_at":"2023-09-13T05:45:05.000Z","dependencies_parsed_at":"2022-09-12T11:12:35.671Z","dependency_job_id":null,"html_url":"https://github.com/af/JSnoX","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/af%2FJSnoX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/af%2FJSnoX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/af%2FJSnoX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/af%2FJSnoX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/af","download_url":"https://codeload.github.com/af/JSnoX/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235581533,"owners_count":19013089,"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":[],"created_at":"2024-09-30T15:37:34.857Z","updated_at":"2025-10-07T02:31:45.437Z","avatar_url":"https://github.com/af.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://secure.travis-ci.org/af/JSnoX.png)](http://travis-ci.org/af/JSnoX)\n\n# JSnoX\n\nEnjoy [React.js](http://facebook.github.io/react/), but not a fan of the JSX?\nJSnoX gives you a concise, expressive way to build ReactElement trees in pure JavaScript.\n\n\n## Works with\n* React.js v0.12 and above\n* React Native\n\n\n## Example\n\n```js\nvar React = require('react')\nvar MyOtherComponent = require('./some/path.js')\nvar d = require('jsnox')(React)\n\nvar LoginForm = React.createClass({\n    submitLogin: function() { ... },\n\n    render: function() {\n        return d('form[method=POST]', { onSubmit: this.submitLogin },\n            d('h1.form-header', 'Login'),\n            d('input:email[name=email]'),\n            d('input:password[name=pass]'),\n            d(MyOtherComponent, { myProp: 'foo' }),\n            d('button:submit', 'Login')\n        )\n    }\n})\n```\n\n\n## API\n\n```js\n// Create a function, d, that parses spec strings into React DOM:\nvar React = require('react')\nvar ReactDOM = require('react-dom')\nvar d = require('jsnox')(React)\n\n// The function returned by JSnoX takes 3 arguments:\n// specString (required)    - Specifies the tagName and (optionally) attributes\n// props (optional)         - Additional props (can override output from specString)\n// children (optional)      - String, or an array of ReactElements\nvar myDom = d('div.foo', {}, 'hello')\n\nReactDOM.render(myDom, myElement)  // renders \u003cdiv class=\"foo\"\u003ehello\u003c/div\u003e\n```\n\nJSnoX's specStrings let you specify your components' HTML in a way resembling\nCSS selectors:\n\n![spec strings](docs/jsnox-specstring.png)\n\nEach property referenced in the string is passed along in the props argument to\n`React.createElement()`. You can pass along additional props in the second argument\n(a JavaScript object). jsnox will merge the className attribute from both arguments\nautomatically, useful if the element has a mix of static and dynamic classes.\n\n\n## Bonus features\n\n* append a `^` to your specString to have a `key` prop automatically generated\nfrom the spec string. This can help when you have [dynamic\nchildren](https://facebook.github.io/react/docs/multiple-components.html#dynamic-children)\nwhere they all have unique specStrings, eg:\n\n```js\nrender() {\n    return d('ul',\n        // The ^ suffix below will give each \u003cli\u003e a unique key:\n        categories.map(cat =\u003e d(`li.category.${cat.id}^`, cat.title))\n    )\n}\n```\n\n* you can add '@foo' to a specString to point\na [ref](http://facebook.github.io/react/docs/more-about-refs.html) named foo\nto that element:\n\n```js\n  // in render():\n  return d('input:email@emailAddr')\n\n  // elsewhere in the component (after rendering):\n  var email = this.refs.emailAddr.value\n```\n\n* You can pass a special `$renderIf` prop to your components or DOM elements.\n  If it evaluates to false, the element won't be rendered:\n\n```js\n  // in render():\n  return d('div.debugOutput', { $renderIf: DEV_MODE }, 'hi')\n```\n\n\n## Install\n\n```\nnpm install jsnox\n```\n\nNpm is the recommended way to install. You can also include `jsnox.js` in your\nproject directly and it will fall back to exporting a global variable as\n`window.jsnox`.\n\n\n## Why this instead of JSX?\n\n* No weird XML dialect in the middle of your JavaScript\n* All your existing tooling (linter, minifier, editor, etc) works as it does\n  with regular JavaScript\n* No forced build step\n\n\n## Why this instead of plain JS with `React.DOM`?\n\n* More concise code; specify classes/ids/attributes in a way similar to CSS selectors\n* Use your custom ReactComponent instances on React 0.12+ without [needing\n  to wrap them](https://gist.github.com/sebmarkbage/d7bce729f38730399d28)\n  with `React.createFactory()` everywhere\n\n\n## Notes/gotchas\n\n* Your top-level component should also be wrapped by the jsnox client, to\n  prevent [warnings about `createFactory`](https://gist.github.com/sebmarkbage/ae327f2eda03bf165261). For example:\n\n  ```js\n  var d = require('jsnox')(React)\n\n  // Good:\n  React.render(d(MyTopLevelComponent, { prop1: 'foo'}), document.body)\n\n  // Bad (will trigger a warning, and break in future React versions):\n  React.render(MyTopLevelComponent({ prop1: 'foo'}), document.body)\n  ```\n\n* All attributes you specify should be the ones that React understands. So, for\n  example, you want to type `'input[readOnly]'` (camel-cased), instead of\n  `'readonly'` like you'd be used to with html.\n* JSnoX gives you a saner default `type` for `button` elements– unless you specify\n  `'button:submit'` their type will be `\"button\"` (unintentionally form-submitting\n  buttons is a personal pet peeve).\n\n\n## See also\n\n* [react-hyperscript](https://github.com/mlmorg/react-hyperscript) is a similar\nmodule that converts [hyperscript](https://github.com/dominictarr/hyperscript)\nto ReactElements.\n* [react-no-jsx](https://github.com/jussi-kalliokoski/react-no-jsx) provides\n  another way to write plain JS instead of JSX.\n* [r-dom](https://github.com/uber/r-dom) is a similar wrapper for `React.DOM`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faf%2Fjsnox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faf%2Fjsnox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faf%2Fjsnox/lists"}