{"_id":"babel-plugin-nornj-in-jsx","_rev":"128-3a94c5bc7bce4cb7d44c87f3c490e709","name":"babel-plugin-nornj-in-jsx","dist-tags":{"latest":"5.3.5","next":"5.2.0-rc.9"},"versions":{"0.4.2-alpha.1":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/babel-plugin-nornj-in-jsx.git"},"bugs":{"url":"https://github.com/joe-sky/babel-plugin-nornj-in-jsx/issues"},"keywords":["react","jsx","if","else","for","each","loop","babel","react-component"],"license":"MIT","scripts":{"lint":"eslint src spec","test":"mocha spec/*.js","cover":"istanbul cover -x \"**/spec/**\" node_modules/mocha/bin/_mocha spec/*.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","eslint":"^3.4.0","eslint-config-airbnb":"^10.0.1","eslint-plugin-jsx-control-statements":"^2.1.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^15.3.1","react-dom":"^15.3.1"},"gitHead":"795128a2077a49d96227c229562a4024f5d32cc0","homepage":"https://github.com/joe-sky/babel-plugin-nornj-in-jsx#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-UoItK7c+uoVm6FlnhtP5rHwV37z3JdK55y1j3UPaN9OK8WP5Wiml4WG4y9xkFmKB1OWp4Wa7F5C1WZ76uhFAGQ==","shasum":"243d69946b0e48e135ba3d6112c05432df042cb4","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.1.tgz","fileCount":11,"unpackedSize":23766,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1s46CRA9TVsSAnZWagAAloUP/jl6V+YBu3i6caye7EK0\nkjKK4LKHEOMxff5eafyCoGGmHbd4KzRWU8W+xL5ihNcNjQvCDPF8xihjF1WL\nNwP9rEHvju53sTeA+J+vWQcOAFeVIRZyKoPwWCyN4EWdsmgChuny9OX+qRF4\n4nbeclrgnfdmorQyk22I0Z3KRnZhtFD1kwCDN5/cY/VtRmII/H96SI9nlI23\nDmX+nUMch8Z8/pTAZcYTV0WlqKlCdSFOl/2PvrHg0I1EF6LgkgWXNMaS4TP7\n45+4HEBqIRuWNzlVvpE1ht2cOdUtheb0xG5t2o8+Uo9JfVfzDSnIy51K6dtM\nTWiIv4Cl7nvqXFKThuaBI/99Ou3m0MZwaoAGfjK18KXVggvfheE8DibPmjDi\n6MOahQQs8emwwrUOBkBL5cqXXvBcpuHyOasaaOvTLqe6urydttFa/3TwfRF2\nUYlXkwXUGkvViDp0n/zkmPLzEeu2tIrwMZVPrWyNpEvJ1tNE9wV5vCUV/o7z\nLBblLPL2Bej6BAN2atUgq6lcgussmNzL2BgEMro3IvVzrwlrvaB0nLuDxvMM\nLu+t+uixRdHbaIq5MHCDLKJt45IFNlzqjZidLKCf33zmgRQu3BWssqnAC+0Z\n7HAACxU93kudqaaki+1WIp//lojXLLBTY0fJQo75Kaq6fLxfOxFrBSgIk4fR\nl03R\r\n=dYci\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8XgMiF7H8ap4RwgzPkRFE5/jgjR+kBH68fp5t8a05bAIgJArY9cKga+EiskfkW2tUOqNCq08FUcdlJopjF7YSA8Q="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.1_1524026937461_0.6056910390846444"},"_hasShrinkwrap":false},"0.4.2-alpha.2":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src spec","test":"mocha spec/*.js","cover":"istanbul cover -x \"**/spec/**\" node_modules/mocha/bin/_mocha spec/*.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","eslint":"^3.4.0","eslint-config-airbnb":"^10.0.1","eslint-plugin-jsx-control-statements":"^2.1.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^15.3.1","react-dom":"^15.3.1"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-HzUhWseGpMXz73DIVUCRtGeKDbbxweWvLWNrscQWBSm0IfWNFmRhPHRGnXuq4g8xDmIZ3LylAx/MVq7hZoHBhQ==","shasum":"83bef26c5abab918e536cf38167813192e40815f","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.2.tgz","fileCount":11,"unpackedSize":23781,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1vEwCRA9TVsSAnZWagAAAJUP/jqha616Qy3Qi9JLD2og\nzi+S8D6R5No2ry3cDMsTzB3pm4Qyn21gBMfHRjY16mB5EGyxbt3nmNILTGSw\n34MaZGCfSi5v1Ua0osJtWNZBusjKk7bIbjLYJE2pmTeIDvA1ouGwj1pcaRMF\n1LfMDW9TxTpJfUYKD4t+2NeSHcGyFo50INrxi13EJftvuftFaLXhbcfzI6dM\n8YTdaEnXfnqSmK/ldjXRVReQDOLCJboNUe9Z8fPt2HxtVyT5vxEi28B8bgOr\nuhYeEnjF17q1Tq44hV1Xohg35u7EDJRz6t96Fv0+xmGXc2yWjeD0ux8yOOUM\n1wSWx49QvHCD2irz/VWxo+qlS7JsBVOaxxg/rVNHuYXLSly34vl5sEbPv7jO\n1iGXCmobs3/iX9zN9re/LB2zv7FzTkS4qt5Dumyp0t1qekeX6TTSXoc8D6Hh\nFbrfAFF923B9Gcfl5VnMyo09kXlx5iu8Hubjzy169nfsRkRt3alPPtOwKkFV\nrUo+BawsFJs2rR5otVcDnqgKvhJkIfD2BNh6Iev4UYtb4etwbUBO0JRVz063\niduVmSiu4Li0JZqyCbdWOn5eKnhdYw8IbgsbNP3Ipv6YKhDrWNtsD7aQMXUN\ngDTL5F+HTnPCcNlI3eOkU07EHhHWYOBLGW+q02msukMawCxp21gfqmJfF1Wn\nQmiO\r\n=Tjym\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJlbfSZ6yxlTywhUNLC/G7dS54/hbym5+q9cPZ/sx26gIhAMxK+SBI2jJp3rgor5wQ70TC6k9l+DPOS/YXJKmLc6rK"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.2_1524035888758_0.2201284821291385"},"_hasShrinkwrap":false},"0.4.2-alpha.3":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src spec","test":"mocha spec/*.js","cover":"istanbul cover -x \"**/spec/**\" node_modules/mocha/bin/_mocha spec/*.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","eslint":"^3.4.0","eslint-config-airbnb":"^10.0.1","eslint-plugin-jsx-control-statements":"^2.1.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^15.3.1","react-dom":"^15.3.1"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.3","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-jh133yHhbS09w35SxvpBCWDRGX6gBPkaQjYQaCw+pqiO3UiQGgKsHnCk4RTFAKbOZDAtl6INYMbY1mWDFeSIjg==","shasum":"a748fde244f621f033689c32e817c4353b0fcfda","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.3.tgz","fileCount":11,"unpackedSize":24630,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa/SZrCRA9TVsSAnZWagAAY5YQAJ7orHGw41hBqEjiD6jY\nYIA2dtxd7/KdLQ9FhiWuTAxhVBVF5p8CLtwZ0RLndmKA1+1driqXQQWV2nuP\nzTYAg4tHxvUiFOFdJE4GYZKF6UVwmll++tUSoH242fJnYijXscTimEDrdPwH\nkzz42L8Sz9VsOtXlSXSG22tbeX3NHie1Nu1P3j32EO4HqKUiegV1BqKgVssM\nnGidO6dPlr7qZGg+DZf8bu4HM06c7cq9vYO7RgYwCvgt8fiddBxnBmI3JsIK\nV6NTExakwZas2pmTCNYZWqxdYSMf7Eybz5Ba04lWYK4Ialhdd4F4d4L7f4rE\nfex38xn3CR5++1M+g701Lt3PBUC9qPxh6mBw+NQ8dTaB69CH0rXGiWMTxrKD\niCgW13SOZvZeCeTSaw+P6rkhTko1bvhO8KEMiSTobKkIb1AXPbE21Pn2v2pF\nQBCTaeVKnMpUR49NC2I+sGr+qrZDP7aFAlGif734QFMx19TWglgfjQwkfg2I\nffmvWc1kPl1EM7tAQTrWJpziC/MW3h4EOuShqPmG2v7J7Bhl/teLHqYCjvf3\nEgxA8ZLY4KnnZI4MjLKC8Dfn57fKAksUmWY04HleIYF4qv1F0fdV6qywu2gH\nPf0ZJFuSNS+tzHVNqJFvZo/YMwUtjfhl20GqbdCn4LEPiB6eNhAku6WJd/i5\nZYA2\r\n=3ALd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBiNHtBG3TX53q5Cxz2VDmgqaHptqbUQHPvoLswYgSVEAiBZDpy7uYSJz8jM3N45sGqsUgrpQ5DCYNfglXcJ5N4mRg=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.3_1526539883017_0.030512416606472303"},"_hasShrinkwrap":false},"0.4.2-alpha.4":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-config-airbnb":"^10.0.1","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj":"^0.4.4","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.4","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-jdwYvyBYXmGkW0Vx6XY8mS1QO383OiAbygWVP4TfYQGdV69ASMLfG9bwaI7rbxtDwqXIPaVaEPlg//ZCYJfcXw==","shasum":"f785e17784f1e87a484421df84d35dfa86304ba4","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.4.tgz","fileCount":11,"unpackedSize":25176,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbA9c2CRA9TVsSAnZWagAAUJYP/06V+aRCy2RSDcx7Ex98\naMCXVMEDwpCnhpzd5RrQzpRHsWiQsx7L2Ipx7aFL2d+8v12UVD0tQhr6tudB\nHPcX59jm2IabTAeHxyanRfNVv1s6fjD1/0Vj53wFwHAscye0dZxW1a1/inuR\nvbq44gUXN3nw/Lw4vLHvsSxxu7m1Gb9ATM5MmM0X2Kj6lBnwqdqNzQGe+scc\ne/vnUixXem/9P2ZW95s2fFcD/drvNXymmmCDRKbyXqWLaCJw+YF8+hEeX5PV\nWanI/ZfVq73p4ShyH1/RRwDem6wSRbpIWgAOWS7Ez+tZqtZp6HRuIuBpdZq/\nPeT9YDXpwvE8OHcFNSntA+Qh5vdQGw+z+IqFKcvFy3ex4CnxEAA/3RewbEMj\nuK9lowdPZtmYP8dhE6xIk/BDR44chtfLfHMj/vdSYx3NjkVIEo84u1XjOCmA\n+bbidfQEgR6zZTX1/E/eDnTZAe8T37E5QXTxr71NFH96xj2WiSlj6trwRsgA\nreHC+rQ8HMCniw61HoUJxVrfYFKzuKXUODWd30poSlOf4AuBisfF+rXQ4iYC\nJ+9UJ/tcNZSiqrDjKW0bPeB6q/W2Fhm/TPkoRl1nRQjYoH2ydPVkqjR+2qiI\n/nle12rVkE2s7nY/OJKiMVg9aVpnk17hBYqSnwDXbsqr6De5bGKV/Ker/zAH\nXuwO\r\n=dMks\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAUbaQu2jGDOtMJ3WT4dR0bfIARdoBuwmRI4mdT/WPjdAiEAsXVDY1udBtbxjjsRPqnhlkKP1Xl9sAiGWkflJK2q93U="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.4_1526978357903_0.1879433843596816"},"_hasShrinkwrap":false},"0.4.2-alpha.5":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.5","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-config-airbnb":"^10.0.1","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj":"^0.4.4","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.5","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-/+KKbYwFBjfy/c2ME+syni+4ZNgLpyLOyVKGgmrEJ1m1GdCE/MOq7HAje2Ye6F1EBO5hl8TcPlLCiRfrBS/J6A==","shasum":"32dba2cd116053b69bcb655f4fd0b784480f2ad4","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.5.tgz","fileCount":11,"unpackedSize":25176,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbA9k2CRA9TVsSAnZWagAA1qwP/0mkS0ghHDVswH3WVSbX\n8JFsLT3AZVWZ7TcpCk2NH0SgKtl1VrsQ6i4R2fKo8AEhe+SM2xQTzNxI3JpE\nOFvc2O3254ZA7uugPwtHRCwAmJeObYo+qHBS/BEYnEbvDhELkOtdCw8/eQG9\nRGD1Wba3E/RFUwdanNWEA8y8YjnTos0W24jeW27hfi304xarU0r/crQAJnBS\nojXXrJr4jCyWxmL+4XQGSKLlFIv2cfwmoyJj4AoijocK1grnWiLFDYT8GF+/\nQEcK2/hNU3vNkp7ZlLohDdIZwxy1jsH3lyjIS4zYKKXhXah6ZvwLAXXhit8K\nF4yQD/MkcvTKmvbiHLoHSksoGtR+Kcxv4pymFZJwBh0XBtD2Z+uXHRLOeyQa\nWylOk3bQ+st9GVlJKpNVw6X5BmkmVZ0Wd3Cf4kxhued+EHtQIaR9+0EsaaPt\nIXR27C0i5BGTFS/2aoQ23deBnR1ly98DUT625JKtFMjmyW2ZRvhPJUSH1Ceo\nQt1unX1PpAIiBQKEmPdoDltbp2egnVw3HT3owJ8vhzrMLjYlqz+i6MK5Y/mu\nPMqievMZk0HFY1nCfS5UBfvUbBbOZLbnlcZWPQUPf8qEXb88bHV6xqWJZXNQ\n8+KRi9opNx/C7GYTW5xmvJj9OL5Hhtei23w7uLSX62jgpn0/gerEjjnP81TL\nNVXJ\r\n=1d0A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGk73VN4iYaK893vBrEnVuYN94yYNdpQoBVi+ssnVp6mAiEAgmUsumU9nBzozhchB+dXVujT+YoTs4AS1gFCa2Mj9Sk="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.5_1526978869916_0.6415828732324975"},"_hasShrinkwrap":false},"0.4.2-alpha.6":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.6","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-config-airbnb":"^10.0.1","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj":"^0.4.4","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.6","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-HDHSQCNXkfcTS8KbgjI1Qb5Xl8/kKsRVf7x4OUaOMFWsGk5K13Z6arL0iSx43YFpZ2cUft9A8D5MmUwtDqjggg==","shasum":"e2ac1b06ed71ef60cb29f4f87de4c54feecf82f6","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.6.tgz","fileCount":11,"unpackedSize":25176,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbA9rHCRA9TVsSAnZWagAAQpcP/RzZ0Fx6Ht3i57sZhBpj\nADyvU8sVI9jtO02mkgrYMeTLk4SmtROczlIOEAc1bfadLClhHfBTgpECJOzd\nNCqjKUiOB7Ah5qN5bIjYfWjRQl7QvG5Eo0fSVcZ5G9T1mz8tW/4Xwdfskpkh\nY5ja+uYWP33AN42yXdSmqCir5fhu5i4cEEu/pvypnezbklkonefIPl1ACK48\nwqGIcURc/c2GwBQ0yNsPB8qqL6rqVxM6QkiMDA5cbuf2MZaKTNq25cYFmBno\ntamcg23KbRnvwlNprNH9aqnF+/pDM2AaxjQHLd0EHSdJ85jIvPFrEOz9PDQR\nHwsTzoLBOwjVRjkIj2E9yCB/6YSPxJYIr7DkhWdK64/tU3LKdd3jD3nmjGit\n1+g2nF+oV4eJo75Mtm59XoAVcdiamyiKPkvIkJ5ske0aE7soFVCA03uQtK7I\nPrsH3fmGAuECuDjOoPfFesQ8t5hRrsD8v+sZKgqT8ZObtsqQLSKLH3Q7QD8k\n+p9FMoD3SMJfIMEQgysOJNP3/yvb552LZkyhxRiDaN51x8XEJNYzoaOF95vP\nN/MmbS/TB7laWUOde5pvkhPDKSCy9LjdIKjmYphL03r+B9uP+k2HiNgoA1S0\ndHz+QCOUkHZYibA22jK3pYmJZjz6ck973nrGOMFRkvQi8q7e9nl2ySXUXnUW\nv2P/\r\n=iz2A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCDMPTVToZ8cmReAvo0kFnkj29+yo21Zo+j3A32PkmRcgIhAPh9lKOg0lwYzBT2AwMYoOCvVs9VtEucS7viqrLvtzoc"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.6_1526979271525_0.31278259683869747"},"_hasShrinkwrap":false},"0.4.2-alpha.7":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.7","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-config-airbnb":"^10.0.1","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj":"^0.4.4","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.7","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-/h31bmw8RuEx0Ixfy4hKNBwBdSBIOX4rkcETmImwncBS+91OTWdovsZ4PUDshUC2//Fogfm7LqSKsn2YZovpdQ==","shasum":"6d738751853506e7acbdaa4777ff2731f42a1217","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.7.tgz","fileCount":11,"unpackedSize":25116,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbA994CRA9TVsSAnZWagAA0hIP/24nnidfHZKnuehgJFGV\nDVHHG1l7as1tcf1fXzEd/bHpaJo9PLbWLex+cKnMth7e2EQrpQAKbbBj/+AT\nLFcwVNBjPqNQ6sIVcCvi3/Sn0QfTSHqUixOdT6KGUJ+utDJm8eqL4NKWaF2W\nvoG4K7JMEgv2LAnfyKskxQb6PL31RMED9F0YXFg7xjP0s03q4ggZbvfnm+OS\ngqx16/zhj+9D+2erEMXqH3FmfIjSVbxmkJM9cbZ3DzaaENgIV+AdQnU28x9S\n3CL1eLQ6om0Vml/dodjC/1SmNabvFZ4iUqrcl1HvPEPCGW5DhaM9DhHEWuVA\nvZzQ1jhfl+deo7A0rRADdk6JPGbbnqwCTaqIARi6kayZFEWaEzbLpRMtZFwY\nF5XE9IQge2QuxOQO29zCZ1L1opeOiYVgTdOJgLEL3QXzdmaicBZYVAd3wtZV\ncJgus5s3Tc+tZx5jU1DrrqY+zEp3HQ7CS0LLMaG69EyUpUtQyj6pb7+q1lgu\nURAOTer7L3lL9CvsjbY3Vwt9Aq225jl4Hh7Ezc62rv+f6+gl2mNDnABL16vt\nOQsHvS226c2+UnKXtnNqJh1ctYK3kkGclUt58e2GwW5EvLDti3GdN+EbImXo\nYQZtXDKrMublMbqNVgfnGa//ZkjHB3ZVODoqL7JQCzR0yZd1AcQY+dxylr3M\nqGmX\r\n=kRyt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGZmmqO52WkwWBVc5PW7QwZhnJon1G29Q/wWj6/suPd9AiEA89TXnlM8ChSLBE2o8EHYdClGPo2JYPAFea7/dgxgvh0="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.7_1526980472238_0.9547442569207876"},"_hasShrinkwrap":false},"0.4.2-alpha.8":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2-alpha.8","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj":"^0.4.4","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2-alpha.8","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-AvuoMYLyuZ663X/HDGr8tsNUtHBNsh61aMUVt8L73klVYvlneWEy8KtdUol2+kfIWkc2xNCF3R4RzblbLVIVww==","shasum":"201e58b6a3c210dfcebeecec207c3e6d1afb3a3f","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2-alpha.8.tgz","fileCount":11,"unpackedSize":26026,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbBM+HCRA9TVsSAnZWagAAOKEP/iixrt76kf7c/UfRVacR\nCSzzpIcg9A7xX7HojAI7UTi20mMh2nJslrwrr+oEhk/u1pIYIY9K8wqpuP0k\nrkDXdkn4EULim8ROCTpH+2OVVKs5KmEJB4XRbHuuz0PST7O1TdsjHdIEndJB\ntFSHqkZ9huKWEzboUc7Ty+rdZJ+61zRjT4pm8YfIYr3i/lJLrtuW2Ii8p9y8\n/L973dF49YPHsg/1U4YM/6ZXColaM+Cvalw8DL105lO98MaMhKjGFDERboJ5\nEIhJp7j7AcQ0FIi+ue+jrjcoMSZno5fA63OYnvtGIWwSLf5c9OouPtyPT2ye\nRUBh5za/aYFJKYYRBWGYNcM1yYb1L2IY7Y7QVRkNTbKdbGmXEGFdjj5u0XcQ\nY77RgOi8blDb2P7oInQNSzi1HeNzXjYIuSEV3lI902yOqXbX+4W6gaqKra0u\nFI5pi2laWcXFDlNZmDy7x6wH1dT3vZNpTyd5DxM/ZHIlXu2OUUGLEr5BvGAR\nmyo09F9Wfz7tkcQczLmyIol0IW1cYOmzuSQ1HCXU8esmh/Zol0ZnrnkjvZzw\n4mAHFeEndQtGpkfwwKrD8Lspp5ReUn9qqZDlcYO/jAoGgvc/xS89C2T8Tvwb\nhFjwr4nNN2hIkhQAsky3y6J8y4LUKjTkJGXYST7tY81eKskzkc6/wizSpKUw\n/YsB\r\n=k8OI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICP4TmN7pZvnF5pe6+ZijrN1WUAA/KjmPgaPGuQic4lcAiA9CUm7YZs6CcmL/AAucldfmrAAPF1fHRPExTztavmIhA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2-alpha.8_1527041926381_0.19716104023804526"},"_hasShrinkwrap":false},"0.4.2":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","CHANGELOG.md","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18"},"devDependencies":{"babel-eslint":"^6.0.3","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj":"^0.4.4","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-3kkIp5KpRX47mXxh7zYCI4KX12t4BC3LEU63ZSOpm1vkSwKIpS0Tu9nnDpmGBvYZryFgHC5z20VMde6k9IyYqA==","shasum":"f15b6f729eaaf644442d4ce960e21684e67bdee6","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.2.tgz","fileCount":12,"unpackedSize":31184,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbBmj2CRA9TVsSAnZWagAAkUMQAJn5LFEm1pHfyP4HIMVQ\nY7V3KIavrY6lCzk8luNiO6wv0pC7Ym/4fIS8Sr2VO7MWwBZAiCHzviShWlUs\nboz/P0j6c2nbzv4BZxp90AaOVGr5hRv3E63LhyjuBF5DY3AzOb1MdXm2S/cy\nJagYL8nAp++Hs0MEeUR1nEV2GoC1kVwzwD9Xonm3S4CITP3vn90gbvViwmRS\nrb9sEgxVJSG3J7Cvr4ykvpF14mdWJsqaKr1OwcxmKf7WFrLVBtmY88LgNa4t\nVbrNmgjrMXt+tSlyYnHHRPXqgbER34okUuSWqn0CLNFaqMto4cTnm/Mpcoa9\nViZyH9mVtZ0yC1Q/uc3+RwJnusHmkBQQnoaAxkAt5B2tvo/RDnwbEHtBMlb8\nd3Clvm5Ux2dToEpsT1G5G5BzRd3GKg2mtDpYaNjakr+f5wu0w07r5K660TOh\nTOxZmTkGsrzEgMSM9c+qwT816SqQ13WOnZ5nvBdC4FXdcwgaAd3/kdME9Xju\ndQCcmRrXBHh/Bck3cmJ+jsfxQ0RXUcJ3MLE4gGrwmZqO6GP1a1usc1MtwRVG\ngSqpNp4ZKIqBFVdnQXhOP5wGD4GJ/tfohzKnndtLbTbhePFz/hTagQhU3m7J\ntJJjDBoCpk0rtzDJylgBdayxcfN5OdFBk7i12DYtf4YiIThFaOHcleILpXJ+\nrFBa\r\n=z0dH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkvxzXDyuAgiTIQ4oniFHvV+GJwQyiSrF85AmveP29iwIhAIYkecfUetbwsRlrMSLxVeurs+gN7w18VLRxCRybHYgM"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.2_1527146742052_0.4626937026504401"},"_hasShrinkwrap":false},"0.4.3":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","CHANGELOG.md","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.4"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.3","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-P6X8fTaENn/j91gcXlsxRIz/Gn3vs+yyA7hY6tem8Fm2DdqG1tdfY52tGiQbKtaE9ipCX3m0RC0CWYh6eNXaAQ==","shasum":"77a4c1bb771a92fa2f98079e8ec90f68120c294d","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.3.tgz","fileCount":14,"unpackedSize":39621,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYYyBCRA9TVsSAnZWagAAVW4P/Rvylecorwq0kDVBz0S6\nqIeG3y27GmchECAkY196FNvG2vvvOVZNql7Hpl50ezky8rtHsyRcK62lQWFh\nXCeAxXLnY5Ghl+MV6uuI4hYtmxP2MCxDV8pyGgOabSdzq+Xpx16ZyBJlts0g\nx7DgaHJdg44VQEPaw2ipj6G+IocYyzMQULd8OK1frpGc78cXbEMz7EuCXVaL\nraJRxnQiMQpLdLhhUOeP60eHzKPPHyKt1nwZk5718HtbC3Crd6TTQPrBN3me\nEHfnhQw0B/qtNo6vq9c/kq1gJFh5rLzxOkvpIs7c1huQ+Y6CPgJE69Bia47q\nL0OlfyvvyZORCvBTPx9BoszwLsc+XyZr84AOipmBpHS32S2BGDa1zz6Vuh98\nx95Wdzt+RgUkyVOZWlh6odaWdzYAKiJ3n80irShZ/ITS2LmXTBH7jKdQnYeo\n2latD2cXYaIOcwk2yQHntFnb+N+sVYKxhAc0U6dIO2162oFxju5E9Sh9L/+0\nizQYKMEG1HVJGH5npdbDWos/k3g+PSnYEM9BsOKRCyEVxGZfJZZ8SwGqIu1g\nAHnbnVMOACV1D1SYzDQQuK6OZPGvbc00fyTH0nLQKg0fyoxJFbvgTNVJEDx7\npuZCWb3h1GQcdqRnmEMmGffpkIEY0jLry1E0VzXvnM/z+kyWjzW5KZGwzhK+\n8rp/\r\n=qLog\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFKaF86lovCQL4C9hEBLhylkoswTeNd41nqoiErBdLCiAiB3GZzeuea4F3FDSHO1SP7EZx5iqXPVIgzh5RaAXXDA3A=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.3_1533119617466_0.7768710532222998"},"_hasShrinkwrap":false},"0.4.4":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","CHANGELOG.md","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.4"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","nornj-react":"^0.4.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.4","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-ru7B2J99DdBnfTnSfXmTUR1Gr/hbtbszbnhB7RxzcHq8d8lI6ukNhkFA7aPzALFrMAzPdWAlhpwGfGu2Nqi0Ng==","shasum":"04451d1a6dac1465abeacca5d4362f2d7cdaa1da","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.4.tgz","fileCount":14,"unpackedSize":40195,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYosbCRA9TVsSAnZWagAARawP/2/fZl0+WKPG7sILeol0\n7YgimuBqq1Rjc9DZgnw0J/DUx20pKZ4NazjNpXfCiDgjM2Z7VTYaZHrA9tCf\nex+XXNKyd7OW6zccsPhDYDB/2kKEL7X+WJtBwoqMoD23IYTmpdjOVoZsay59\nyAcNUGO04KD27QdORsTcqQsa9I0J3GMHcw04tmHmq0x+nv8UMnWME+F9/0tY\n0K4NnL5K2GzClTd7R0z7srQt5avY7SxqGvj3PV1wq9WDT86FgP+b78PbOcCd\nkikg/SNkWdgttEJ7XE1ajM0PIZbhybw/oYRfNFXfeWKKaABWkZSA+rW9CbOS\nLOMVa7FjrAnYxT4o0YlMaGizq9SVgZn11DyoA9bA5Kjrxwx3YoRnH2peKCWi\n8tGDS94OHBY4BvWBByH4F3YDTGyFp2jlUP8+nRsTXkcsievEkyPtjC1rXjuK\nmOP6X50I4fVcQSNXDlmz69nj8lJoV+PON9Id7kf6Lo4qADGAI/iXnJZjbs9W\nq5Mg5ycaXa8Z7J1ewFqr9JuYQbnRUVQibvAS0cTaIRt5F8GkM4igqGg2P6xj\nQ2JVvS12ShOb/SFzoz6Rxra2qTKxpVs5i0EIsuXUwmG3Hoxmu1uktliIxBgR\nWBuJqE7So7dVse7w0Yq5pXiFJgXDsVjHpDPGPgDHDYi5y1rSPhetAxVjDtKw\nEMRl\r\n=4d/L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBjZIxAAEh2AG0NhnGGhVTb43J/6I8Mwnr6sanJV0iZbAiARRNN1kwPVruHtssqzaCe8LXwUd81enuekUxyaLyAp1g=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.4_1533184795523_0.35458088006009336"},"_hasShrinkwrap":false},"0.4.5":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.5","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","CHANGELOG.md","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.9","nornj-react":"^0.4.3"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.5","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-2QtsTpX/29HZzmsxHI3Ije2mZDTi3sfo1zyCvcMQvqMRdqZrtMQGA3vgrhSd5TNP5wHl23rtWR5RaV+lXKLhww==","shasum":"39ec91e5a4b341a523a18c06097e2e52f9e08c1f","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.5.tgz","fileCount":14,"unpackedSize":46535,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbbY53CRA9TVsSAnZWagAABm8QAI0mCwMYEqtFCuH7VJTX\nIQSJiP3f+EeTNjLViLdTZAOtnFHW8Da1GWdmhG0ftIc1TOrnbkKYCYCmB0PI\nga6bP7HJ5CAZoRgctBgNh2B6ubtuh0/kn8cZJsSkYlBuEtNpIqYk3rjXjHUy\nwqDFbrwDIHXzX41deOBFPS8Lm0l5TYinz4VC7CAKsapVgFaZRE351eO8KH2c\nTAHAu8eJrr85kQvgxiOZOf71zA9z5XkX1V7ETlN1zw5l81I7nyfT9hjeJDfl\nH/q6af0R/eM4shzB3Ap6309QNOjBQaq3ufjD+Jr9DfRSrwexZZFUh/3bJEtB\nk2CYBQm076kgANR5tO6gm3U1MPwBSnBr6oRtD97g30O9msoIsGyg2TrKzy9Q\nI8r4tI8bDwQDg8/zVTSrl1O8fUGmxrd/WWtlmb5Js+OUql0OANZRWgl7BBkP\nI8Prbzsat9opVsOxcrAUUzLCq2Gjq0LZUMZZVni8rL8EquXOmR2tuvXloVIZ\nlwFNjIp2wrBHNe8u+leCfgNG0DvzxjrTgF1JP/GZV7DIA0YGW0l3uGRgCqte\nAcqlHTlZEFFY2bACUx1qhr6+DzM4xR1Ksgua34jFzf5NCJ/zyK4vyzVSsS7H\nE4lZExa42NGkh2UG2pZE7vWmJEKjc32B79dg08RPSoGkATwE2hloZtxXa/MQ\nCgc8\r\n=wX63\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAfRMv06BHC3HTUdkEuFDOPqAAOnX7cfqeOokdkNBmNZAiBeqIasQhquvrOqGvKpn86bAeixQQ/o+fUvqKoHAYhgUg=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.5_1533906550996_0.046192861429236176"},"_hasShrinkwrap":false},"0.4.6":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.6","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","files":["src/","LICENSE","CHANGELOG.md","README.md"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.9","nornj-react":"^0.4.3"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.6","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-oAPOmk/nJQrvO4WdD5f7VAceQaqQi75l6drlEBfzkqJt11vMvzyShmu6lQcCeOX198kCExPd0438uUoB7Nggdg==","shasum":"1eddd0acfce3a737b9206bc741c71bc59999232e","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.6.tgz","fileCount":14,"unpackedSize":47271,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbflmhCRA9TVsSAnZWagAASHIP/3zST2mNLAC5psUrjuIq\nXmUcHowVmtyOtxrU5gKPsvplbB3ECFA0taDiEHG/BAzsUwaWYADs7zoxSxj8\nDSLZU31SQO8Vvg3ypuWFiHzTmacdl5P4SUFQSfuJKYgcoFlx/ex4zGcSwBqg\nYlRIf3qLz1jRFG4ortRrgtZBrCR4PkhK/6ZHD+SuuF2/A40GYjegzBKDmC8K\nm+bTiIdNBbtXGipf3Ih9y5ZETund9A+7RUJk1GsHCOAWRQ2HFE3tVM3PS2mI\n8eJnPjcZA4B1ck6kY25mfDtaCjgzodHzInEJ4PWW3uHucEranVnPUxaegueu\nJLzgsolHcJ01OhtO4pOhZVvLNqi4h5ooNJJs1sNXHIcz8WLS9DHns6j6bOIY\n2uk3NEWfA8x1mWbZS9mEP4/gvJ4Ph6XCFXHPGr00hFZ/Wg3u4bjxdRJm+OXw\ny9HNtVCJkcKbz0NmBa/N3a8at2ruv60Gq+M6EkWYTy4QKDAp+qV9nXeh5nIb\nDwufmnzKkj0+UiMutxxIdQPHqy7TvoDBy0Uh/Bn32REyS0jZJSdj67GhuB4N\ngfqLuufNYfBgz+Lr0zPPLsgB4D/at20oU8HySbz57KeCxvA5kY9Afv47PRSw\nwpIlKEIhsygcy/hIgo45jt6uqH1sOJSdF8W7crsnOpExusZiwk+EbKpfq8pg\nQk6e\r\n=lfgg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLceN/3GzqK0P/zADinChV7NiU5AmMJYQCDoUWLZkvswIhAPXdmG7NaauXXJPpENv4epC/fxjtXg3PtZ1WlGV80FJ1"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.6_1535007137069_0.8276194150079632"},"_hasShrinkwrap":false},"0.4.7":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.7","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.12","nornj-react":"^0.4.4"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.7","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-ujWuiAHvD5hsyOLB7C0si5qe2kgoBEhE4xyTKL8FRIhSgPmHha2pnSktJ9SQ/2f8gUgC69Xqa+0/iNPeYkut4A==","shasum":"12716c9ca43cc26827ccd1de63fdc0ae842c5995","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.7.tgz","fileCount":15,"unpackedSize":50563,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbj6pOCRA9TVsSAnZWagAAOcgP/1a/uzdKsa8cRkk/Zlhb\nU5gIK8lW8m3a5m6nTPOSB/EWKTkBcVgXyML7H6746pei6pkJ9cih/7ds9cKy\nh6ezecBKyuMmrquNo14LwtAkSUuMioHBF2TU9rcT8BBUqCKde0NBOdqIfmwX\nc5+Lwvbfisjsf3sXRKwjY7jWUSMxLTtVVPeV9sNc/AYwB8i7XLalR+qFJhFs\n8Xsgw6UrFdRnpIAOhYAl+mbUf+vul4W2vJ8iHHFMFnMf3i8SEjgYpmIkLyns\nCSQWVWoSCg3DcPdPKilxItJe2/f1h6m7MfiyXFs4oaCN3vtTVWIvKUxnJSMi\nPO00GKWyxHRDjlevPOjOJGqvMuCp72AZAa9Nz+aeeoLYauILYMF6dPvKgdaF\nE2/OBkv1H5+YwJzPR3/OSMERBohtPnZ6//zlfEEXROcAUNaiNPdgljs/qMz3\nlLOXT5o168q6jN6fIASjGMIh2//LItXUlAa0aZ0qrn2a6SJrs39H8z2yqV15\n0OJlimyoX2hDPYLi2KRprxsZPYewjvjgkKKa4h81Rhd7S0nYRo1d+KaGFItT\ndHQ6YnbTH91Js1/Ya7IGsHLc0VKi8A8tyAKi4YrpiTHHMpEivhO1z3mnVn3l\n4rivIn6tLA47UZrU+hAV7PR2rNfJVPx6Ol7K+gYTybcvs3NG4TUM1d2o/tyj\nKdfX\r\n=0SMZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBa9AOibBU6/AqLeDUx/Tz79i4m6fPzGjwbirK9e9P94AiEAlZAw6I3CeQyvuaLGPZGHMqs1/uoDBNC5PcUloAmYf/M="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.7_1536141899380_0.39514984410810317"},"_hasShrinkwrap":false},"0.4.8":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.8","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.12","nornj-react":"^0.4.4"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.8","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-fo1h/MFIDrpsQrhEb8e6K+Ics7BcMqRHcKBHVhBN9Z71D3frApyuBqM6VwkfV8FN9KIwFKp91Xf1mEFSQgRtJQ==","shasum":"954d11c25494a47ffe0dbb73330cc1958ca5c2b1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.8.tgz","fileCount":17,"unpackedSize":58687,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbpHc1CRA9TVsSAnZWagAAGvsP/1jYREAJxDoo+Mj2JcIT\nT9spvQngq3Lr6ZAaCh32gOzCqzsntpN1g0UoQibBq6x9drjfgPbW38Zc0IvK\nUl0d3gRyOTtpv6RzoYkhrTm98BrXKzsabtoFgyJxoHYMM1Y4+ykDqSRgwvxL\nVYL3dy++mkhEcYQBDkc5Lt3EJc5YXcNbN6KViO8flNZWHMbxEZlRBb5Mx5yA\ne5myk69sdAq44X/RHfhBscTdNRrc5JUUhH+49f4zWGOVsL18kYnio5HAnqjZ\nfvZaQ6ByYQda+nrRZU4H0lx/Z9yBtC30x4+0VyAdl9tpULAv27r0kIBothXU\nls26E5BVrj1WMFhT3IXapKd/tkIaIUN6C5fhTN/7WmOQCWN9XylZtvlDlc7Y\npVzZfSHUUhEA+7zlrtHCKhupcTbr6uue9C7TmuI+mH3ExdIleW4q94nm4CID\nOjEkGK1hG/S3Guo/TGmj04j9Pss0L++XxGByxQ6zXulH9nXndTHZvt3TStZL\nwSM/Ru4uERyjWLGVSGwyLAp8h7R2Rz+nBb6hhboGrMRrJqBLWmQko0e+Omu0\n4iMWV6qsWg0t/ywB8iEwh3Mmdmoz+AkFVA4ZaoJlhU1I/rcLnC3COTEzWQUJ\nDloCC79dhaXT69p3fGqhzH9sIC8Jv6m7a5KOj0hBJmkGpylJrMGbwhhz8JPn\nKQmm\r\n=1Fc4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD0WzenG/FqaFi5aBq56BaJA+tR8MTifT5zM47YByRligIhAMAyVPYD0fOn0HsN1ChRRRbql8S8ExYMkI77jngw7fSk"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.8_1537505076733_0.5847794519623717"},"_hasShrinkwrap":false},"0.4.9":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.9","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.13","nornj-react":"^0.4.5"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.9","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-CUhoCZK5WlZVnGM720WrxExzNCTWD/BpDmtwZH73waZogJiIgH1XGUarFwCTvApAAxAfGDijmx35oKhMyLizIw==","shasum":"78536653c6acabe4ec898e3b28a7fd0a4f85eb5a","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.9.tgz","fileCount":17,"unpackedSize":62930,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxvHcCRA9TVsSAnZWagAAvuUQAIW9ji75Hg/LLB2jSEA+\n3qzNjmvs5ZRkYToMTF9Be/PkuCPYYTadLl6kRoM+1ZfUmLhezDTFqlSf6Wyk\n4qmA+KoC8f70qutANnu3c9YYNwLe+GWQu9yng0x9+1kRynLG7h9ZI6WEaV30\nivUEi0uLeqg9tx/M7NP8svQQ+sVebeDT2yAtmwgrVo9tQS9rZM0+JedmLvdx\nCWQU/gwoku8AwaE8qRMGgePX1i0upoKQkhIvOMmzLkfnH3Pvg+6ZER2t+VR6\nKmLb+JZkaIoK4ySZmQ+pZsa37zqm5HB0iw/9CGm6ZLWrciT3j+WqMmdzw5TS\nclN/vd5jpRgfJ06LhxaxCd3L5lBp73aNXgHBUR1CN1HX9Dg6AlkO5ZkNi+NR\n3PLex0lWE4VbMkTB86oXCe0APL+YI62SaMAaflkqqSnmMVE9YerxI7Oe3rTE\nms4mSjjLUsTLzWjC5mWwyijPkgJqCz5tDouR/wySVozSNSkJkSc6URSL3ieD\nj5YnKhbHOOKSeWA4WlpGX38wpyjtjnD+VJ9mrynWoNucktNY0wUwkP5Jz/2/\n8TslVCA9N7cA7Qi5r2tVpb/ERow9lwzbDHjbjkt29ajghz2TccuhIYCqXflw\nw5a2HOehoeY5XPKiFmvwzCTPZmJidR/hjmIZj90KtMeREIZalYtY1s/N9E9/\npBA5\r\n=ftgs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID1RUfnJJo0YWRSwT7mMZ5tqsp4EsoZPqI00vvuwqWnkAiBq/JfYVCq4lfewAMGOJqaR0ninjDva9d6oOVfjknnVQw=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.9_1539764699617_0.5467693138584444"},"_hasShrinkwrap":false},"0.4.10":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.10","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.13","nornj-react":"^0.4.5"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.10","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-00ELoCttYGqxHNIsu0n4rW9zFCpFryVIh6yGj+CtNi5Vdq1FgWo5HjDGh/yNnnGLl09eL+wMp8qjfO28oWRRPg==","shasum":"de39dfe7077bf97bd8b5c841e8981500a108f177","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.10.tgz","fileCount":17,"unpackedSize":63392,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxwPGCRA9TVsSAnZWagAA4LwP/iLWQJFcMBHMkH9VtCwa\n1zPuDftGAYKK6f7qUbtBYE/0TY1nWxr+wDthS94Zco/s99MaLavUTUoSKwC8\nK2ncTH9GkLXf+qfdW/aWSjsctxJ6HFPFNT6qlaE58EpxkoBljNCgiyrwkjZT\n0DChlVYPv350aDAvGRYwpZchw/vW5Pl8mQwVboAACagJEggFtgcIr4I7qboJ\nvXknwjJVPvZwwEsQmn76wi8UPjhUoDwYF3IIrN1+7zrBWcEv0nizgGVLY2Gn\nLieO3n519xLtNJSdkWFQIUhJ03FkkjGw7dGTBWiofd0Rb/qUvfrE8s/61vnH\nw7+LcVLHZ4GfX7uZaPuHVLcXs4cRycxACzqXCom5iv/4oG6GbnlXELzTJ5Zf\nESBy1HUnuWIa9a/kU7lOTgGAmhrjTgAJuxWXcff64wbet5a3Gu6VjxSOQxGL\nn9/Tj53lGWKkfIylw6X7oFWImWz1O6F+xXLVmmlFbHNo/nTahYvmKK8kt0YM\nPiE9putU7txtqtAWMQbp4F6NJLYFWjk+HpbCZmEeRv8T6ELIuUNEfX5FUYfd\nTqv97/6cocpYolKPY3JFfFd5USeTwy6zg3uyXULlxiW9Qa0Caa07VVIv3pAI\nbLgsJ02VcU1GsXzyhNecB43XVXVV7Mmzolaur5RBgRtPlH9BzT0+6YLKkA12\n1+7x\r\n=M6Tg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbzTLLqohWBjhcZXgWaoQHMpUiONPDpKDqWVuSzf98eAIhANi5qZeBUWCLc2ssZrdc7gciiuhB4iyKTtbznMzTq3zM"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.10_1539769285208_0.8586084229344217"},"_hasShrinkwrap":false},"0.4.11":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.11","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.15","nornj-react":"^0.4.5"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.11","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-A2u8ajNf9PWAakQaG1Y0XiUPnRpvnLsulWZl4+VGlfbFI4AUWIu3nURYfy14d9w6GiJ9bQIg8YyZNZ7e1RtNag==","shasum":"f8da58098d212ee05667704f66e561de6055aa5a","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.11.tgz","fileCount":11,"unpackedSize":47376,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcENSpCRA9TVsSAnZWagAAwjcP/RZMjMvymdHUFVd2jGSD\n/ySy39rMyw+1iCcpIviXk53SrxkNx3H7rmQbPQzRME7uhqShs9lFnw28mnta\nfKLAmLjCKnN8DkZiNERwCQ2cnueitHEKOo+qEq/YIUXQWZelZb33ovkoAqNt\n13syDnq4xZLMt0JDhAMPny+8RJOaB66eMYmxnHnzcN7Dr9mPSJ+CtVMO8iyP\nYhUd/py6GzbtvSnWTDR2juQ3uY3o8ljJbCfk9zc/TiV3Y5cLoOTHQlLhlkzf\nb6+aVrb/6YxwjFbNbOuDtMn7MpvkNhYVrIBdvQK9zlxU0RJVl8smUVp2OtF8\nJBl0a8LAXRBTiZM3p+spCaK1d/zDbifhEydnwTRcvakivmhLmT7POlcmjeDM\nv55cxANHCCJuZ8JXXtgQiTyKEP4Hz4F+aadgVyejBUK66noq/WG7XgFwvCNU\nRtpudb+9c6dhF480ffNi24ajuhUFHEl9qz3yqjuL8Z8zuu4U2/OEYavs2MTZ\nY6UWl4n8ZnUE+0G1LF1HmhCGzNWexZRyuLmeNwGyOip07//Q3s98TOTtC7Cv\ndlbadThbMTxiSaIyrfr0aFBtOvAXKkvO3zwrXNW77kkfVQHmiwh+3WD9Yztx\nBpW+gSIuv/oNdccfmzkxyurxFn/gi/0HUTDp08donLxdVH/qnb2+MgG3ATIg\nENKJ\r\n=ZahE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdqqDlfVL9Y9vEAg6WDMN/q3ypLVSSqvEOInZucTpOwQIhAJz6UciTH2m+NRGjVypmesldN8R5pIDoc79x6SHrsC1p"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.11_1544606888538_0.49351998493796834"},"_hasShrinkwrap":false},"0.4.12":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.12","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.15","nornj-react":"^0.4.5"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.12","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-CNL3drl8f0T8rQqFjXXkjb4Z20mDQpJbINfwkrOODPg+7+zmr/+pkmz4GRpSXXmd+s0D7XG7Dgw1KWJ+bRXR2g==","shasum":"a9300e7764e79e5b8320bb4279f3e194e2e7b354","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.12.tgz","fileCount":11,"unpackedSize":47412,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcENpsCRA9TVsSAnZWagAAHRIP/3uDKDixvyUO/eW7qs5f\n0/OkfDeMDuU1yP/GDNDetHIQD3FM931MpPUpMWRZ7XggMUTK2MbruNhiKozU\n3AAcQO1JHZa7Am6zEP3AJTuBpbXIB5TLdC3ecPbmFqwTBJ8eNp/lsHjp+NIM\nldRPvP/tP6vICuUWj4Vy6tUS4IQBvJu92j9S7RvReUpO7iMg9g/AKtRGqAy+\nwvQFjSIugbeY/i1GbFnQz3GbPNidKTWWOzkikqc4IWFmNZpWYFoGcafLrZUA\nIPb34vxWQeoT8eSrVnrCIJ3P8ezVCdV2iUk2KWSB0rBSPHK2E96ihENPtjJ2\nTYpNHudeOJwEWPQWvUEg7gbC6DUte6M+h5mV6M9R/YOCy5y7mHpktU3sZyaK\n+LOzD9u0ErNlX0MDgnRoHiRhIqmLyrz+65Rrg7xH58YYy2PAuIcl/+t1PTV5\n24Px23Q4uRYAKbS25xEqcYT0MIfyrgICP+Q/ok6dBECs+hMiGit29zJquZh+\n85elW4CSXrXcqXt0EaA37ip24R5jQuUuu2W0vzzxslm3Of8oTPPlokbNlTj9\niHmrgKgWhzxDV94aB4dig2cNbgL8RA1b5dHLEYbcw95pERGdgP2+q+hqdk5d\nSt15apsfrjKuFgjSXlcj9zajgbQz60SaL3HszPeH+GymTRczvXAJoFqYo0Cq\n6QUn\r\n=hsn1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLLnBTXxLngH8YiGBbQMF4FjZQubvFPjsNERZ4K9ddjwIgaarYUPJKDco25gvYlm9KS9QjubuBLsWoomRQTpQ5GNQ="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.12_1544608363758_0.9822355965746421"},"_hasShrinkwrap":false},"0.4.13":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.13","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.16","nornj-react":"^0.4.5"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.13","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-COaz/xpMw1mxjyzNCu0GTN+oRhrK4uSrN6v2iNf3tNonkehYxb91mrw35VZ0UGBeebX6xsdyGjdxV0zkEDNaKA==","shasum":"c0617dc1c75a50caa2691eec24e7f700aa6318ae","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.13.tgz","fileCount":11,"unpackedSize":47561,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcE3wyCRA9TVsSAnZWagAAci8QAKHontGD3qWi5XqLxjeM\ny4n/HFWJZoWmHWpgMCNZWWU0TPvYX6ayP9Myxi5RMvFceHzWdFxtgFOAFRY3\nouLESoHqAxRCxkjZq/3pRzdMz9CESpAs/FRZ8wyjh72amCBEypI7yylOCPTC\n6Fify3gkWoLz0KALOSvYS8XeOHubAedvV3UgvqaS+mImg9I0NFcRk1Lq8DB8\n3cOC+pAEa5duRmpmXMQ2FZZ3fhmFGbc1gN+04V0+DBC3uP/RU88wBKRdgrWo\nYFbVgx77EvNuYtywYP4+3WMJyaXCNq9XjjogVyEonAxXx91SBnnrgetBmbSD\nzWr4CS6CJkuOVGQNa/xgBiWQQdWg9HHmuDsKYvdjqkf97rZdr6sxNkqcnUEO\nEq5IZ/hv+o+/08tgvrKCJPgaIs3G7EFzJQ6h9Sfg25KDtLOR6HfenOBopwOC\nhJz12qk4S9AtQpP03ZA+7y5bYS4CwfRasT7pJzMSv6lp/Qt6ETww7pXFdpqR\ncYtIWnOB/HAefaQ5AkMbAVRCILXY8TGhEJs6XKU2dr15t4S8BFCT8WK81W7a\n4OuhfLDlOvF8fK9Lmf7eOAiY1rluXQJiO142Cmm4+y3S1PzHMC+saQbAgUIc\nDnkVXnx9ocoQbcGr0Snyb8eT5h49Xm0UZlxQQ1P2g9FHsai1+YtU8dVEeq8n\nXYdD\r\n=6JS8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDc4glf2yKuqgUKDC2YP4we3syVodOeeZqkJv42GImaHwIhAMeZu4uEWHBEqBUkJ0ii6grGPc74Swy8IYDgJjeisAdu"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.13_1544780849306_0.40361324711477153"},"_hasShrinkwrap":false},"0.4.14":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.14","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.17","nornj-react":"^0.4.5"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.14","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-8AHKkjuNlMm2kFViC3aNGcBHueWPJ8i/nxuTySduECtQ/hLjyaWdN7pr30eSslZoF5pWegr5/jScvVQjUyNz5g==","shasum":"1c95f05ad2f98bfa50c8c0947e045cfa7034e662","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.14.tgz","fileCount":11,"unpackedSize":47836,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcG1feCRA9TVsSAnZWagAArRcP/R98UJ/sXGGccyjI4Pw8\n2WIZJ0TTFxAJp6E0psB+WrW4KzdD4EI+qGESTCE92DD4T6K/kU8PUipzL+XM\nFA9J12GUJErl4zJ7bmJX5wouT3XCB8HqccBiwKYMke/PD+P+kZIxPRFxlyQn\n8O3rO68s9P21moTbkvTZg588MaQ+Y8fNrRO+OVUjEx2itao5eFoRCeRmHV35\nKaW6Eonh6nYIPdVcRLEy2WoUN7/oTRtO6dH9hTlyZ2pa4KDwxC8SN6puRTYb\n9OW2rJgv+GdPwosW6pAMFLD91d1Mh54DBYbTjdpkmATxMvGqdEUY0X0i0zwu\nCWNU+ZtbwhJrSv6kkMA3AWwKlSOi7zcyg/bW4O93Ps3HaStkiuRCx0K01h6O\nhPGxX7IaTXYpTFbBOVr9GjeRGZLAuR1gOqFy6y8YgC6jusXl5r07ongq7b+Q\nGkMaimJeLNQhGpH14fq9cCIpOWoguMKybF8mPtcrGAQVBlUKeWiCPlsQ1nsn\ns+qSqdS9QWJLhFFwG6ulEPBw7MpVxXm1W0aEAheh06TQzMtckOBQemCkNG38\n84jaDZxnrCYJ/wfiOV+Z7grjFaIC/g5vKtSLdTq/ivrSUfkA5zxTmdFodGBZ\noFkmzATji+rqE/WDuLWaqJFWAFARoYsKMQIGf7lmkzIJpfUU+QNIVDJ7pw4L\nnjyF\r\n=x4Gr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAtk8Ckht90P42B1d785wxgLHHdDbQHVNnBAYi0KZcs+AiAVdlJUqXg6Ea3JuAofQhjMiGSYca5fyZBETBYqxIR6sA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.14_1545295836970_0.32214832333519783"},"_hasShrinkwrap":false},"0.4.15":{"name":"babel-plugin-nornj-in-jsx","version":"0.4.15","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.17","nornj-react":"^0.4.6"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@0.4.15","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-FgsoaJeBIY6dK9HWvphylCsYMtcAszWAjeFmD9lz6IuS41x0L2KPHB+EYbPtZQFUcge5TdGEVF1Paru1mAOfmg==","shasum":"d2af001b186eb0a4a58f7bede937699216777a88","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-0.4.15.tgz","fileCount":11,"unpackedSize":48017,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcJ0r9CRA9TVsSAnZWagAAz3AQAI6wx85cRs+hFCl0EhH0\nJThS20s2GJOTFW6+NafKUakWo0TjyaQqNdxPKnBDsboHN6aS90Xi8WLGpidZ\nJn487IUwyGeXe610HVdhG7xBRMnn45tyykQII/Pv3bEopVpQP4WwpVWy3Dj8\nKGvxvNYht2yz4vglFbXl74ARl1B4j8GCvJhKmyCuLnGwGTv7ubk7sUlTpYSH\neTlUxj/5nvT2NyUoVYOPNzvQ6zxXMEgFMGNlgBcURjzLijhxhHdhfwR18rlT\nHgPvDksPS60euq8LzVtHdJp6g8I6DCSdCKj17Zo3L76OBJHw+IIOaFyRHz6k\nFGvRdYCTP6xVYqyL+vRWgh1Lndp1Wrag5QDtfK6NTseutwpxsNOSwl/2OdEl\n/RRyCycVBznFROdhdKxOHIVAeugu5/m54c5qdsYT91HX32A80KiGgDYRaOB+\n2dKrpE4H00HX9FVgbUY2d429yfT0drhFG3ibX3uYNjfprjaWMySlzAwMfOAQ\nwMcSjEDbCe9OUfwI5gdZwmyhf8HExjSU1Ubk51dASgo8CdYIGWtRFoclIUE2\nEuCJiva6m9ofZ00uwT/XxqBPQ6R9FmhwjNN+9bdauGS2M4mKqQJbf7BMpmJD\nmiprq3WYktdSF95nfjDweyKgyS6+aeNdUmvve1MolAMI1hm78gZlqQSRXgQy\n1TxG\r\n=Qdo7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCItDrWZnhAQNZ20mkNh8/55sDy8rO45vDyN031QcO9BQIhAIv5/QiK4LR+P4akVNDZO2I6re52xGksuxvVhZUqWeoV"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_0.4.15_1546078973013_0.478121999443641"},"_hasShrinkwrap":false},"5.0.0-alpha.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-alpha.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.18","nornj-react":"^0.4.7"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-alpha.1","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-CwGQZxZmtXelr7w7lCR0KLy3hJl8MEBgqn2IollLNpdLlzjIrkDjnXNkVbOM1x3+OWS2bC/XlgxUKlgM7OHaCQ==","shasum":"96063d5b05b7dda00eb192ee06b566984550d752","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-alpha.1.tgz","fileCount":11,"unpackedSize":48347,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcYkrqCRA9TVsSAnZWagAAJV8P/0Z6hrSx6EMwCqIwfKNO\nhZIEMILZWRdE8vhktllm6+4ltSvnE55QhBv89sM1qMs9PI3WGeGp1ou4ZAaB\nr8ZTno5jhAD/LBXzssGiywBYCoWkYZ+xtHW0JMB/By+oi2+nWHIPUDPN0rvA\n9EfaCPArpLK+uRpGqxR9V/JgCHEHlkwKmCE/t22l04L7hGvpik6rw1J045hN\njqyeOJOy+TRT2MQ024Od22tYkLEkEWf43e35vHvhyUNb9UBFsIErx0XeGJFG\nDVc/AQyKNHrmVVv1VRa7FaxtKVGFGhvggZagGVm0tDfO4aZo4kw8Qtzqhus9\nE+2SmgDQfaOTvvdXbKnBpj9Eo7QaTcAL2t8VZlYWFwgdrTdQsw3nGP5vtvI+\nctvHOyRbDrY2MkYH3/SgQo3bd5djTpbPPRBr1Ymr+Zl23HpmCXn8FDXUlQF9\naRsFeEJm34gBvYJaPAxS3wzvIEGO2gjzBe1mB0l7J+OTYmBsWorXHBx3xrE1\nPDbSnVU6QHo/AmR9gPSKWuSAIOpLsVd2zxYg8lx5q0F4ak0PDox958ZEbfLf\na+3LwIlUVKr4dkMWz+hRTyNsjybBKkI2yakOCgEXkmO2cmZ4hR6veJwdhwQ9\nwzGINcp5FNYuf5gXwQwANc9+v2Da5wW/Pcc2xN7lOWsQMu8e3ky8AJHtVcks\nBagk\r\n=24ej\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFfwRmBRCyYe93YDZcRR4nov8eFpqbzzvXDlxRCR5wGyAiEAhFTJb67azhb8MAdUk9wYhqYZkbNQmnaGx5NwBNLmY6c="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-alpha.1_1549945577535_0.6332222914980763"},"_hasShrinkwrap":false},"5.0.0-alpha.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-alpha.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.18","nornj-react":"^0.4.7"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-alpha.2","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-EyJej6jTLUCPU1FgsuWiTtt5LOs1L2jJYuWnHGBGPA1jpt6GJ/9/rRhB1WDzCkxD/g3TI3FTeQVE37lAWTzLdw==","shasum":"89b3a42c2d38c8cf57f82bab22a6ab9c1ff21ac1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-alpha.2.tgz","fileCount":12,"unpackedSize":48977,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcYkvfCRA9TVsSAnZWagAAs0sP/jWRmQm9jwTm+XzUhDcN\nZc/WZ3t0v0VmtMgadBRr3l/i5j2e9aVkKbdjV8squo9lnQLf637r/pxUkejp\nxMMgLdgUetqNfBd0oiLoQyjDKQcOnFuub5iuT+GGgYXAtFZnf9ZyFXzb4DFM\npoTbEFZgnY/C3fZo/StCZ240CHNOxPUEUf0h2xadSvnP+STHx6tK7dfDpaRN\n8TWfbqR6vmQJp6O3fR9Jklp/l9VjeMyW/hxUz3j7FG/7V8OZVRUtXQOJO/U1\nJaoMUSxs2slKWrCqOdy/SQBcbuW6ZrJJjwP/GDF/MP5zpd874RGDKLv4PoTH\nSVniitEW/Y8iYTiWm8weeRR0E1RZOECnQELmCcxceDgZq6TqdNZRqaRmhuWY\nRrwIzKs7EWTeH1s+qHdwGkxq/s4TbIPWyeRbGIQO8IQCsMKuds/n+1tgsqV+\nGBcF42HdmQldq0aGzMd2q1rV2R7hg9otrUgCfVacI47M8LOT9Mbo8+l8tcHv\nx5IeKdEF2Z+oThCr6Nxsg+StX9AI0242+tORL5qmOPWWIBzkqFNPau5bbRYq\nhu3dm9hQNatS9AcfJ/nlAZt7Rx4M7Vd+3C6yNm2HnSr9Zpc9t0+KMJXfhcHR\nnVpcZHjQ4gGBdXkMnK3Pp/4/mXXnaf8c9guAmZaq6eiUWaafBpqhBCYWlhmt\nhBKf\r\n=tkPL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/OhbNISayG/dw1G0HrD+WKftploHBLVFXMIm5KjEVzAIgavZGcXXSTPo7tn/Pgmubh2mhzEBRxN9PhyCkppCouFA="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-alpha.2_1549945823303_0.6803639768199432"},"_hasShrinkwrap":false},"5.0.0-alpha.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-alpha.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.18","nornj-react":"^0.4.7"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-alpha.3","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-fw6M+SwjAJHxSU62qqAP8Fh4g1qUl0lfrb4HoxweF3xVwcO/3u3sV4ZS+0eMBWRX3LGKwJuWKnbbymWNp8OHcQ==","shasum":"326382e872a6adef01b5a9cf9be65cfe47f7ed53","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-alpha.3.tgz","fileCount":12,"unpackedSize":49294,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcYm1OCRA9TVsSAnZWagAAW2wP+wW/MSyO1AsdNe/6AtTN\nIQuukyTMG7y0TTO1MXirVIZOQttlZ+A/TMQ6tByVTnMHKacrDnjkd0Xoh84A\nDUiBX8qnu5de9xKYRfEVzpEY3Tm5wXKfCrmhagryEiIiim91Hs1dEQv6UxL6\nerhWcCoSnB7ZTB+60uq6NZ33Kn/9/Arg4BVP/HLG9oaEaoOOSaxKCAtijAAp\nkrlMDjcmllNn/1m2eeQpv9TMC7Ph7PliYg6sXApBVe9+Cti1wEC0+1iC2+EB\nX8m4bFPMNSBaXa0Bf5u0eCtCQ/P/E0Rb5hCbD6m2mn6KLsGdvO0hc89lzi1V\n4eSkz1qM0aq4qXDqLSw8V+LgY+8+8q6kjSyl7SDQIgYmZ8L/pAOuCjnTs8rg\nwCWDS3asQ9EO0CEKyAqa/0Dqoc3Dty4Q9ZATY1aQ9QcpFlkFX+yoLQNTO1IQ\n+n99wr9TBexsoHV20vlKTVmrgltlDWmSjBEnKiKx8hQE6l9Ig5Ed5dfP0xg1\nFJWaN8M9ci1bWf5CKz1Q/rwsx9RyRozbOFyIUSZSBNrg4XQcvfUDqpFOB2Na\niesEl9zupjZfuLI++fkkzxIV+/xanuObw01YgLMq7NwDlvQyemLi+RKKU0CC\nISSrO23PF91smO03mDuALUlDBmcZH2gV94JuINnjIwRMxKL0FmckYUAXs9lS\nL/qx\r\n=dcyg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/MsNrj8td0cWtzLmRa0AqYbjwMomkWro4BURib05qUQIhAJINMpSO6MnZdaBXFurup/TwKRQqC4DJUDnpf9k5VcFk"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-alpha.3_1549954381606_0.22334741694961124"},"_hasShrinkwrap":false},"5.0.0-alpha.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-alpha.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^0.4.18","nornj-react":"^0.4.7"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-alpha.4","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-GoVicfy3ZwKELEB+vjIl6YRGTiEVOS1+5vI2ejwerl06s/jzQiHz8ooHyT4gdDxiqCwdcXT4Q+YjHJajpX3+ZA==","shasum":"5f9c11d8c2522ad99bce4a09ea0c7626934840cc","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-alpha.4.tgz","fileCount":12,"unpackedSize":49520,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcYnnXCRA9TVsSAnZWagAArvYP/2T+gzZf4+L7ldrTyMJT\n8QWfscYRm9EMXe/CXs3BH+qSGq1KXQ+zs1mw1wBwjE1vGRag5pHwsV31ecim\nle80IrAdn8Y8tYLIi68Ll1IF7VuJ7Xyl96/NSa9JxXhgc6es9V6OwhcWkVD+\nGRNkFHJIfi8AHnwVWBBIkrUPdcY8AZxZnmk4lRwSWqh7igh6bLxzHAurn8E3\nCL+Xw+45/LRqaB5iquDNbD0fcA+c1JZQtoL+fhXFTh+qRfIQOPc+KQ40Hag9\n0i/xmRhD+uqpqXENETm/nunwp2UC0RLlbFBN50Z0hC5/SqLad3vrCQZGGR5C\nZaLqtitrcA0ZaeIln9U5E/bPeEFKLZ14GIFsps2csoJctULKz7sFSS+dK02r\nC7/ZyHRpOospiLSnstvAPCrQWZF6o4IYfSWtS+IVtSB6molsC+vh6eoGYKNk\nMM4TJ3oQBnITmqXuyCgI+KRF2yqnLy/rkKN5up6FItsCXA3Sl0H0hgomturC\nfjYawKajeNkkD7zP62t+uTRb99XzOpvKmnqmrth2SbQnnbmymdXhMXI4zvmq\n2d2EzXUGwurH44cBfUBEV23rF2kF8ODekELQSHbp68u5l7VCjXbUaVJIABzk\nY5j/2NUWC7KHZpzSe2/er7dbqWtYDawqVHNCVKO5WPnBE39PBvyGliRq/AeN\nuZXw\r\n=06Rg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHAXswXRcf2ksVEISWnZa76ULzfGnovsKtWLiYal5NT5AiEAwq+JY8EglnzqbXgXBZW9VqARX44nhtUbSN7ydbzZ28A="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-alpha.4_1549957591219_0.5620304547438546"},"_hasShrinkwrap":false},"5.0.0-alpha.5":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-alpha.5","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^5.0.0-alpha.1","nornj-react":"^0.4.7"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-alpha.5","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-ZAV9s+VF0QQfdwh0QJUv52tLGoMqwgcwo6iife7h6uXLPNpnO95z4MagzeVJQN0p0b6OVD/bfrvEnC89JfEOcQ==","shasum":"70ccf4e8bbbd8f83c68963f7ce5c280cebd0fef1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-alpha.5.tgz","fileCount":12,"unpackedSize":50180,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcdlPeCRA9TVsSAnZWagAA6bQP/iR8tZ2sjCc7K7Sicp/S\nznMBTQSjGzk28QbnxVk1pgwsQ0t+oI4ShlRS0x+VsIkaDnZLfyj/wvym7Y/F\nqQlHLUea/tUnTv77mFzdfKvWXBDOZ6tqQFBewbMFECUsBIbcMgeFyyKj+TXu\nOSThP1TLILbA7sd2hFtMrPA/jgrvLB1izcTvB7Z00aQbBOVDstc4ParmlZfq\nN8py+5SvfqDdd3k7/D14GQi+IsdaDaaeuOd+IpCPY+UMtZKYSYXozOBrheYf\nz5u4HHL7zh6SFjQq0nZxJe1WLjAltt3m9bahd73z+GzJKasLlEQ6lrR/yA6n\nHpeDpyJmCnNj6Y5n00SXd7z53sHqWHxSlFERd6diKU9vWwdu2HKTceYLk63V\n7fY+23XeYQ1eQhHrM75cJQS/3cnEztrPD6OvJR0YGdYwkN798lBf3xJsWvCl\neunepDo+vZbrqme269d60+fTpeulUT3nbnBOSnjKNqpNNW7FvAQgGVdmH9rn\nsNow8pgjH97bKJVhv1z+uhasjYLhKjYZmN1PeRdibBU+Zqmac81EEMxN+tdT\nK5KLC6l2FMUVZbTqwMqJQugYBW+fBNiUdNKXDIe1lsr8yN2aGr4KKlKUDRKy\n5gTVZ2FeHr92wy58aPEkNMoCcj6A9fgKrRlPhggwBcqRY8KA2hH4xqNdu3Z3\nxqty\r\n=aOD0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDanxcnYYgmXbJWSNbpuHIuhVf6wqB1hN9eVKKiW4ONwwIgFldgBBCti485opUf1Xz0JDImv4UrdG8/rIqbhmMU0nM="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-alpha.5_1551258589400_0.1658623470145313"},"_hasShrinkwrap":false},"5.0.0-alpha.6":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-alpha.6","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^5.0.0-alpha.1","nornj-react":"^0.4.7"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-alpha.6","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-dYlndP1WovJDQfrC7AfsahuiHqnSd6KMflOJ/Kg+7F6W9w/Q0MQwsb/xBKr+4z7eiGNGBLBIrZaC7Yps7jDVBg==","shasum":"f98e4657354e94edc40107d3ababce59d20e6dad","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-alpha.6.tgz","fileCount":12,"unpackedSize":50435,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcd7NGCRA9TVsSAnZWagAA1lYQAJEjb8WsRw5OG649wChz\n71dFpRGhp4dO0gaxLexYPrDe92HATxfKJ5GDYg8JupNIk/3HXNLHANMWJAMs\nskeA8kbnugJp6lQAg3Cijuju7AkB/GJwu4TkX4g0ILpUhgM3mvK6KKCpRPUx\n09h9Tr2j7iX0ruc6Ff8Ixf2J7SwDqb2xn7c/Qgq5eJPP6drhsJzcK1JKb3Lq\nSuDDwsJu5c3hTRlnsjE428iAQQITmpGWx2a0w5MJamh0wEaLGPQxSfFlQmIJ\nIMhhd5123UC6NNKUCGun7R/rvt9dAukpe+Or2i1qmibr/tku68SzObZ1AyJa\nCrCvMW/h/oowbGzmTPdIJqNUQGEzhN+50J/us3GRb11C+FWae4gUDc2iCE37\nZ5HLpwZdPkSuuZVHoXXNq4QX2w8K+QwaxJb02n7ecBfcnLL9EaQ3mpphjExD\n2HniGcKOT+CgYAds7+qWQLWEa8zEUf8JoVCuxSqQQN2SYl55pO468K5/oHCe\ntt+A6yV7lYr1FBsCtZomAy1hHl9gF42jwmZNoaNuDM6cfs0civzYw+EWzQVm\nAbeJrzFvqgPrsXk+PDS24cA9UpwUYzkwXpEIbFZi5Jubv51BEO3Q1s+UYW/F\nyPr0C6l+9zNR395CFsuK5aSeGgJxzfDwNwrKGvuuHzaoBbuSQHcwc+sDlw3l\n4EUx\r\n=+ZQR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDQYRPkNZ7ctv0OUUp7OELnaF77w/tAfcTgsW2mp9XMZAiEAxF4a2ys38cC3OStX0ClxASxGK+Bdhq18aCqnsaFc1WA="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-alpha.6_1551348549899_0.7283931003218067"},"_hasShrinkwrap":false},"5.0.0-alpha.7":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-alpha.7","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^5.0.0-alpha.7","nornj-react":"^5.0.0-alpha.6"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-alpha.7","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-skgcK7Ah1GBxapS4yu/CRjB4gCrfrrG8nFiXJy2NFBDNvTYOD1B1K1JK5THp0j/UXQhVegQEGblPkrjKfsh7bA==","shasum":"fdbccbec1e04a5cacca5e50c213157bf2c5b198e","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-alpha.7.tgz","fileCount":12,"unpackedSize":50443,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcgmd5CRA9TVsSAnZWagAAPjMP/0wQBOo/1IKqy0xD3elj\no9ZZN7ZD2Jx7wrIuwo2ifUlGei6YcXO4PgftciGooi8kpj3X4QltY85nzgPq\nejXyI4gAzYmsQre6PKUrzyRCwvOJSetvwc3V7cdKwAA6jqECWTdYNvL5Jdsj\nay70f1ltELen1QdJ6Ypji7zeFjhfWy2wSFMwWv1/5aPUoxaHmtApfbLtNABd\nwIYlWLKPJ/qRH+N4FB63prD204el7HZZrZFAgO7F7fsP4BPaxpULtbMjpm/D\n455JgsKb1fXw6QX9A58JWpcK+1KNap+V1lfFi8uMiX5G7bSie3fDagUzhYii\nLEGFWkxYRI/VTEc5sTWwSFt9d86URAybEms+EFFw3uaIktsxxiO4hjqk7pdT\nXGzHFj7Ql7TjJvzX+02Xo/XM7XOHE+bQJHfl/QF7lIXnOpjXvS8d4XfXXIdT\nV/byG27+rt92IZNkJFBbfUb3Yfl083+xGKGR3tziGd0qPnLW/OjIPacR1HPr\nf0a3n7o5ZxD7Fhm7sOiFniuZU+nWa+L0iEo3MjZtVrFbSApKvTmGmHSdZyTH\nz/Gcpu367bCrhM5Ryto4WApVwO997OGnltER6xR3squmuKV/jmTfRxGyJD9i\n/RlKKtXjCIrf6OGXAmFrINrE32T367Uk9MFtAiabVXG1uVUTXVOJAjtAw30D\nig3p\r\n=4tzB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFn/sVWxaK1kaHHdXQSfyuYhq11upSmrLRQnIsnm/C7nAiB67YIEuYqbQqr5NzYlWbInEu9FG4DEAt8MyWZbs/3tMQ=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-alpha.7_1552050040688_0.4012714823174801"},"_hasShrinkwrap":false},"5.0.0-beta.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-beta.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^5.0.0-beta.3","nornj-react":"^5.0.0-beta.1"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-beta.1","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-8ns3gpE64iA3JKW0rMEOENUsFV6pL5j3ST/eCA0fP+iLJwcIfIOBdLLYTRcwDCRk1e8yBCFyp/CJxvyuUJAk5Q==","shasum":"24e10f5db1e2b0e174a1c0252d038c69d62025e5","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-beta.1.tgz","fileCount":12,"unpackedSize":50757,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciORlCRA9TVsSAnZWagAA8SIP/3KL8NiWkkZoxxKqc863\n5tPkfeLMe1iUWCUYQBAQ9sY2h/kjDQv9JoDLBudL8geOXKYqv7PIvpC8SzWR\nFujoWsHd7ubf9q1eQVmSUiMf70ywSPkt09Gtbvrkh1unjehA6LSJrmSar4j/\nB3zoD/vfPcAlYea2f2SK75aKCUeUrKg3TiWGNOkmh4K05odTkD8MfTIaNn3M\nQ6Y55EGSQ6cYKDOfLXgtz06TSmBc11aS4ZV4g3XDpWRNl3EEXNyTuOJAZGpG\nWnewpQjIXxSGtqK3d/p2ECaRc4vxTwZuyVMOPXKqnpdhPtQAw3yud1u2i0Wy\nlQDWnRLvAvl2BvSxa5K1CKPqzh2OaA4feonOSAUoy9wTJ638FFSFq50BNCp1\nKstsxJH3Jhm06gy1M15oMceFeVwOt+ESoc/+YmFx8q77lGyad/NtNSeFQU6o\n+zM+SODPrrCbTdJ2W7cITxPEkWAgg/4/auT0SMU57bNPmTremcqL4IvVeuCs\ni1Cf5h5zoj+UJA0GD4uKuRXPDU57PI8TsawX0A4x05D5cAxJxuzVKY3+MhCV\n3cW26ZHTUlCU9IrB23ssTDXwGPuJarULB6u1+Ro+JVOjt/PCqFTxvVsgcldK\nouu8WTewKcDom8vAOxvEnUVSPNu6SfWjrwHQIAecZegVTA0iykn/XQ0huT8Y\ny4vD\r\n=NWGO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBFiirM9O3RU49VpUgJSiFFGKAG3WaXSAXgx/bSJyikWAiBPBTdmiyVWbzCJRzJxGUO824vt1G2qsyT440diRUJwdQ=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-beta.1_1552475236713_0.33815560964517144"},"_hasShrinkwrap":false},"5.0.0-beta.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-beta.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^5.0.0-beta.4","nornj-react":"^5.0.0-beta.2"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-beta.2","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-ukXzPSL9XvXy128gsvhbXjHba6LuOk8AoC9I2/ulvoxF8KosxL9WFtd1EI3hSFINdgqxyDRV/7bdB0OwDGHypg==","shasum":"4bdeb19e20d65f2fc114b7380c16ad7e9ac741c1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-beta.2.tgz","fileCount":12,"unpackedSize":49656,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcigLWCRA9TVsSAnZWagAA4icP/2j0m/kBr4NBadK1iS34\nepLe0lqy/TgcNqoBb31EqsjDDecaXBx24PWRHVIi+6sYWxKch79gurcaaJnL\nnN33Nwb70I9EnUDHTTePoYgmyZDyc9moeskRJymR+3MM9vV0EkGtuY00gA7q\n5xWN0bH6EybEfBiVK7khh9wl4nmJfkP75ixsZORU9KV0qIGDnW5kjHDve4l3\nq67Zl6JMrB0kMOUIm39Fd9+rA36Ya9XifojYRB1TKnLFzsIkcrzPr0nikiPY\nSpVEXccuRTr4HT88JoyQxABS1+hIYXJg0lP5JbGBNnopBMp08U8+xYpNmUov\nGkP7bxIzKunJ2QIJNLlVMtBwaQ8lLlC6wyf1hadsDGERnCq4vDBsu3utcdK6\n1oBFjCaDzpFLcAzj7UdCUOX7Z311GFZFyHSny7GQEyXXAjnl+xpFc/ojCjkL\nTnzSVzm5jQ0XsIhKmBI/bwfU8JOT0rjKqKODf6G3EYvH7kH1maRF0BPLfx58\nxLyYonQfetAWNKa24dXAZmyNM6AISHcvdznuw31VSh1iatP+3JHP2Hu47hml\n8RLMMtLZX/fGhkN/Y+65HvQspcNvnlP58X6dDKct4wpM9/XYZzLIzO1yjEjq\n8nG8XXeFKKxa+z+GefEaSCvvTavMzL37V9DrXQdP8AIxFetp/ZIo77sK2zzu\nPw1y\r\n=CSJk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA8cGJMdhQ/T7lnokYxFWA423Of6rHmvcmgBDMMf3Uz6AiB++Lbe+9wLsJU6re8KtOodYmr2j9BmXDVuebnsJB0wdg=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-beta.2_1552548565670_0.7350655321040236"},"_hasShrinkwrap":false},"5.0.0-beta.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-beta.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^5.0.0-beta.5","nornj-react":"^5.0.0-beta.3"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-beta.3","_npmVersion":"6.4.1","_nodeVersion":"10.14.2","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-vUdlwH/p4T/NCz/4LJqk3H63EDU3jMM56FtPmdU2C+3W5EryJNWcm7Wa6nxc3e3y4iSJjwYl7Kt3nx2MWhh2oQ==","shasum":"435fb47325b50c5d54d5d03a2d28085d1d1fcb5b","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-beta.3.tgz","fileCount":12,"unpackedSize":49640,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciioGCRA9TVsSAnZWagAAKN0P/1upc7U0BBpigVD5rPFe\ns2uCuVVSYagrMaZPqLVjipAZL9GtgcyrFfUS/4XhcmnqpgQyeoKWntloFWBg\nF1aQUlEfyfLrGzqA8ILrIp4xzkM/fG0SUDRVODm9fQUx5Hr5m5a+nQDYzB4d\nN17icaIPbaPX2TDlhoQAd8GbMj+UAkZ9ODioZiQC/yLRgvKIjv5cu/BRg5TC\nqx8C64BpXddNi8RJ46LwL6bR4FfHpIuQ3z4HoXNshvX+SU94CeX8PpdH/DQl\nSHMh4waF2CzQUo4KD0ZVk7SWUUIfDkvw9ONye9QLWGEsGNWrwaebykrFlPWk\nJhiWeTOCQEDaZR8BGxkxwAlQ7XS7elV5IuSvb0SWK53hSfWaBJn7781fNeCp\nBLfqZc8fYjFy/UtmGfXKBd0yPLmAlhKMxSJ9/nbA6gyiVdxGhPV7K5UtjOyg\nEP3wgTUrJ51vWmPrUigMvj5rHEup84D/MY0Un0nuI8mRR+1X2CTr6hic9Gcv\nQhr7qSJflfomfpHwAGVhJi2Rek8urap9uAAgHd3RQppBT533fuevWyJvP3Xm\nDwjVXYn5umXmexsmJ5pKUlh50Cd9C+onCrrpkD97SrZGVV2++eBDlNqlf6qL\nggpxeFLvC0Hdd5kf+uBQML1/t9S7SV6eYp1ci/B2E600q9MiVyHIrSnWAIyn\nCCwA\r\n=pwuR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBCBwjXmChwnIn9pmJpr5wht1bLyp6q5Ve267tXO0VZyAiEAiQ+wPDlQP41YyezKjeT01BdwaVCi5LeauKbSXxByYdM="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-beta.3_1552558597333_0.743115707478758"},"_hasShrinkwrap":false},"5.0.0-beta.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-beta.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"babel-core":"^6.1.2","babel-plugin-syntax-jsx":"^6.1.18","nornj":"^5.0.0-beta.6","nornj-react":"^5.0.0-beta.6"},"devDependencies":{"babel-eslint":"^6.0.3","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-react":"^6.1.2","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\n  </a>\n  <a href=\"https://babeljs.io/\">\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\n  </a>\n  <div>\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\n  </div>\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\n</div>\n\n[![NPM Version][npm-image]][npm-url]\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\n[![NPM Downloads][downloads-image]][npm-url]\n\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\n\n```js\nconst Button = () => {\n  return (\n    <div>\n      <for i={0} to={10}>\n        <if condition={i < 5}>\n          <i>less than 5</i>\n          <else>\n            <i>greater than 5</i>\n          </else>\n        </if>\n      </for>\n    </div>\n  )\n}\n```\n\n以及类似Vue、Angular的指令：\n\n```js\nconst Button = (props) => {\n  return (\n    <div>\n      <input type=\"button\" n-show={props.showBtn} />\n    </div>\n  )\n}\n```\n\n还有过滤器：\n\n```js\nconst Button = (props) => {\n  return (\n    <div>\n      {n`${props.name} | capitalize`}\n    </div>\n  )\n}\n```\n\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\n\n```js\nimport nj from 'nornj';\nimport cn from 'classnames';\nnj.registerExtension('class', opts => cn(opts.result()));\n\nconst Button = (props) => {\n  return (\n    <div>\n      <input type=\"button\" n-class={{\n        className1: true,\n        className2: props.hasClassName2\n      }} />\n    </div>\n  )\n}\n```\n\n## 为什么创建这个插件？\n\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\n\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\n\n## 目录\n\n* [安装](安装)\n* [它是如何工作的](#它是如何工作的)\n* [标签](#标签)\n  * [if](#if)\n  * [each](#each)\n  * [switch](#switch)\n  * [for](#for)\n  * [with](#with)\n  * [fn](#fn)\n  * [开发新的标签](#开发新的标签)\n* [指令](#指令)\n  * [n-show](#n-show)\n  * [n-style](#n-style)\n  * [n-mobx-bind](#n-mobx-bind)\n  * [n-mst-bind](#n-mst-bind)\n  * [开发新的指令](#开发新的指令)\n* [表达式](#表达式)\n  * [过滤器](#过滤器)\n    * [capitalize](#capitalize)\n    * [int](#int)\n    * [float](#float)\n    * [bool](#bool)\n  * [运算符](#运算符)\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\n    * [a .. b (范围运算符)](#范围运算符)\n    * [a <=> b (飞船运算符)](#飞船运算符)\n  * [开发新的表达式](#开发新的表达式)\n\n## 安装\n\n```sh\nnpm i babel-plugin-nornj-in-jsx\n```\n\n`.babelrc`配置：\n\n```js\n{\n  \"plugins\": [\n    \"nornj-in-jsx\"\n  ]\n}\n```\n\n## 标签\n\n### if\n\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <if condition={a.b == 1}>\n          <i>ifBlock</i>\n          <else>\n            <i>elseBlock</i>\n          </else>\n        </if>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        {nj`\n          <#if ${a.b == 1}>\n            ${<i>ifBlock</i>}\n            <#else>\n              ${<i>elseBlock</i>}\n            </#else>\n          </#if>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n更复杂的例子：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1, c: 'abc' };\n\n    return (\n      <div>\n        <if condition={`${a}.b.trim() == 1`}>\n          ddddd\n          <i>aaaaa</i>\n          <elseif condition={a.b == 2}>\n            <i>ffffff</i>\n            <div className=\"las2\">\n              <i>888888</i>\n            </div>\n          </elseif>\n          <elseif condition={`${a}.b == 2`}>\n            <i>gggggg</i>\n          </elseif>\n\n          <else>\n            ccccc\n            <if condition={!true}>\n              <i>bbbbb</i>\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\n                <i>ffffff</i>\n              </elseif>\n              <else>\n                <i>eeeee</i>\n              </else>\n            </if>\n          </else>\n\n        </if>\n      </div>\n    );\n  }\n}\n\n/* 输出：\n<div>\n  ccccc<i>ffffff</i>\n</div>\n*/\n```\n\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\n\n```js\nconst a = { b: 1, c: 'abc' };\n...\n\n<if condition={`${a}.b.trim() == ${1}`}>\n...\n</if>\n```\n\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\n\n```js\n<if condition={a.b.trim() == 1}>\n...\n</if>\n```\n\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\n\n### each\n\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\n          <i>{item}</i>\n          <i>{index}</i>\n        </each>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        {nj`\n          <#each ${[1, 2, 3]}>\n            #${({ item: item, index: index }) => {\n              return [\n                <i key={0}>{item}</i>\n                <i key={1}>{index}</i>\n              ];\n            }}\n          </#each>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\n\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\n          <i>{item}</i>\n          <i>{index}</i>\n        </each>\n      </div>\n    );\n  }\n}\n```\n\n### switch\n\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <switch value={a.b}>\n          <case value={1}>\n            <i>1</i>\n          </case>\n          <case value={2}>\n            <i>2</i>\n          </case>\n          <default>\n            <i>3</i>\n          </default>\n        </switch>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        {nj`\n          <#switch {{${a.b}}}>\n            <#case {{${1}}}>\n              ${<i>1</i>}\n            </#case>\n            <#case {{${2}}}>\n              ${<i>2</i>}\n            </#case>\n            <#default>\n              ${<i>3</i>}\n            </#default>\n          </#switch>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n如上，value参数的格式和上面if的condition是一样的。\n\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <switch value={`${a}.b`}>\n          <case value={`${' 1 '}.trim()`}>\n            <i>1</i>\n          </case>\n          <case value={`'02'.substr(1) | int`}>\n            <i>2</i>\n          </case>\n          <default>\n            <i>3</i>\n          </default>\n        </switch>\n      </div>\n    );\n  }\n}\n```\n\n## 指令\n\n### n-show\n\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    return <input n-show={this.props.show} />;\n  }\n}\n\nReactDOM.render(<TestComponent show={false} />);\n/*\n 渲染结果：<input style=\"display:none\" />\n*/\n```\n\n### n-style\n\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\n    return <input n-style=\"margin-left:10px;padding:0\" />;\n  }\n}\n```\n\n在`n-style`中也可以动态嵌入变量：\n\n```js\nconst cssProp = 'padding';\n\nclass TestComponent extends Component {\n  render() {\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\n  }\n}\n```\n\n### n-mobx-bind\n\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\n\n* 基本使用方法\n\n```js\nimport { Component } from 'react';\nimport { observable } from 'mobx';\n\nclass TestComponent extends Component {\n  @observable inputValue = '';\n\n  render() {\n    return <input n-mobx-bind=\"inputValue\" />;\n  }\n}\n```\n\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\n\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\n\n```js\nclass TestComponent extends Component {\n  @observable inputValue = '';\n  @autobind\n  onChange(e) {\n    this.inputValue = e.target.value;\n  }\n\n  render() {\n    return <input value={this.inputValue} onChange={this.onChange} />;\n  }\n}\n```\n\n* `onChange`事件\n\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\n\n```js\nclass TestComponent extends Component {\n  @observable inputValue = '1';\n\n  @autobind\n  onChange(e) {\n    console.log(e.target.value);\n  }\n\n  render() {\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\n  }\n}\n```\n\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\n\n* 使用`action`更新变量\n\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\n\n```js\nimport { observable, action, configure } from 'mobx';\n\n// don't allow state modifications outside actions\nconfigure({enforceActions: true});\n\nclass TestComponent extends Component {\n  @observable inputValue = '1';\n\n  @action.bound\n  setInputValue(v) {\n    this.inputValue = v;\n  }\n\n  render() {\n    return <input n-mobx-bind$action=\"inputValue\" />;\n  }\n}\n```\n\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\n\n### n-mst-bind\n\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\n\nstore：\n\n```js\nimport { types } from \"mobx-state-tree\";\n\nconst TestStore = types.model(\"TestStore\",\n  {  \n    inputValue: '1'\n  })\n  .actions(self => ({\n    setInputValue(v) {\n      self.inputValue = v;\n    }\n  }));\n```\n\ncomponent：\n\n```js\n@inject('rootStore')\n@observer\nclass TestComponent extends Component {\n  render() {\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\n  }\n}\n```\n\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\n\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\n\n## 表达式\n\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\n\n```js\nimport nj, { expression as n } from 'nornj';\n\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <if condition={a.b == 1}>\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\n        </if>\n      </div>\n    );\n  }\n}\n```\n\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\n\n## License\n\nMIT\n\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-beta.4","_npmVersion":"6.4.1","_nodeVersion":"10.15.1","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-fPj477BkrJWCqN2XKvBkVMWcjbgphitn5oKddvKS+g89XL7Jr5o7HUlqZGRxSbQyVuEQ8OmBBJXn4Fo0y1O8KA==","shasum":"f1725af775c52bdd283efa749f5010e4d0c20855","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-beta.4.tgz","fileCount":12,"unpackedSize":47897,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcm1KrCRA9TVsSAnZWagAA81wP+wZpQx6T5e1BJQUVwxYI\nVEnqu/fJ9eyOyoQL82DyYUmBonlT7NzxUbdemrVXuY+9ei6ooCte1EGcHBkJ\nb3LSst4Bl77IzpxWXvl2X+gznGVhCYaKrrdI3ZkTVFikF+CepMxMhKIbSm6Y\noNX5cDQ5vguwp74+fMJ7Y2uTSlrVlalau7a4N1XoNQNGP8swcvMNbEzZKYz8\nlJPrt3lkPjNzgnICug+o4wEHyOD/+l8hAg4iiZqHacdCf5NFMZdqwRoFOTzA\nedqIUacsrRILlQpjbJMs2dZp7Gp9gpIl385gDKdcIwO5XjGIbl8hjW6BuUh2\nTTCGfxUyNRRHu9ZxnNecYEsf4wg7Z0qlN991VH92vy9qLUbPzi6IVkdq0cmZ\nYa1UdDiD7qK4SwFoltGm5P8s8iAobZKVlJHrdBAr6FfAxW6YLz/LHMdTA4MD\na/ip3RX1IxUb9IVyzLXIwbkY/sQwOXsX7A/F9RuvD/aq/juRLd198cS5eJrJ\na6+IinCKVDdklGl7T/j2tH1DvNY7RyqXVjyEz9ar1rB9oVmZ4d4bwq/5KtdS\nDWaQMuMRf1wqPxx4Uur0PjK4cExDwO30jM7z9ndnGy/hXfG1f12VeE2SUqa+\nEHZQsNriwb2Dj/OQAKZQmE/tVkm6mtrthzkhrgDjjlfsYhDVWo9Pir9bl/WL\nhJ8p\r\n=khCo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCN8kmXomeA41KSUaZFxlJcPg574z6HQlygW0BXwMXTkwIgPoJ78Vv+Vg6rwUkbefW/juji9wS1cWalektEe2y4DRs="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-beta.4_1553683114487_0.10864825622553753"},"_hasShrinkwrap":false},"5.0.0-beta.6":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-beta.6","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","@babel/plugin-syntax-jsx":"^7.2.0","nornj":"^5.0.0-beta.7","nornj-react":"^5.0.0-beta.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-beta.6","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-mDCa+IKeg9qalaLEVEO3lMrsVSUx41pmxvMRg4v8v7e/cfObdaJI5pjsQOiR69538YQa68epWTC5JZzZn1LvWg==","shasum":"9112e6f69ed18fd2562757045198dd7dd5899baf","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-beta.6.tgz","fileCount":12,"unpackedSize":49738,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcoYtkCRA9TVsSAnZWagAAfQsP/2SqKuuHrd7UcAXjmJzO\nHuKUO7bDlOptLoUerOsuye+g95NnJeoIAPuY8jLOEz7iaT9bCfrxYzYUYX62\nyxAbyG3htwOBRJVCZ2Uzj78jnqXvv3tl8QNHd3lFv0CnyWxqEgfvagaO2xAl\nyJP5J/rO5zRMB+ZEtj5lsuehYtThiTxe7Z06evJQRPOBQsKoOXisugrsHEki\nJNwDVrehkaXE1HiyOKSZbLnqI8uEvxJ0GhWGzdmXVRiWUjqoO2vjps3i0VNH\nT4NzpWvNFbWb2Gdx0/VT3+ptlt3cgtAgASVZw1z4/DZS5pa91b90qde1iYqf\nwvz50LwZzxae+a4nw0HXlCcKxYKjvheUTcEUsZ4X92rc9505PFlVNkDkzGYi\n8YTX3J00M4p3EVOiLpv9Pg5AG0seYvYu2vkFaVI1bwflVGR/nsz2FjnziJxm\nJoidHWFG2yzOht+8UnUWLfRMSAI13zwVh+Bxvygo8ahBPwIN2zvGrmuX8dbd\nxs9hK+YyZmyHTC3c7Yk++b+4gGpqIYxC+ibUKaSloTD1jKkI3+G9HSKUyyMq\nAw0Ccm5j32X663BsVnvbLvfZWEdjyELvj1ZagHwBxDsbS02iIvhdCNIUobOj\nKainRGtIDRVSM+f4h3jepMRtXl0MxWbyJM5wMuKq7H8AFqRvX/gcNeym+Rz+\nbLAs\r\n=PNdP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBgyI0I+hwctfoALRwdXdmN1OCUI1IGtuIFWVQTcwy0qAiEAmQgoqAkGjhz/Qntdeyv2BlLQLNY/BdNrbQaaCjqqu98="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-beta.6_1554090852003_0.674009051313551"},"_hasShrinkwrap":false},"5.0.0-beta.7":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-beta.7","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","babel-plugin-syntax-jsx":"^6.18.0","nornj":"^5.0.0-beta.7","nornj-react":"^5.0.0-beta.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-beta.7","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-cD2yD/TAd751BEfV/iAPw0wyp+ZR0ACXmzkPDgyfEdDaFUbjjEIO1V/u4h6IO8VGmFCCfQbjYEHli4rIH7DF+g==","shasum":"f268a75ef10f29dbf0d7567c9555e9bbb25f6332","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-beta.7.tgz","fileCount":12,"unpackedSize":49729,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcoZN9CRA9TVsSAnZWagAA4xEP/RSVvRSK9/IMBBFaegvN\nrwSQ5VybyrEZ9hKyoAFsshjMR6UHQn62gQKXUK+ZwiVN9ZnxONu8Z6VxSipb\nGF3RhdwELg5U46cFNaTq1ls6Qpffm+YKOxdOLKfxTD9K65BYsGN9nG6cHnTZ\nhnEbaSAdkbgguN4UtIyWMol6PESk+JmClbKVSioqpdRWhTJubyDu6CjhhsVa\naU0KlNOOj8gfBmqvC4ygwqBMK9vrMnCEpsKUY7hK/CJM9Ug9hgRDl4ctqDyc\ndwnjk27bumx/31ZD0crCcqqP7j+SokNdHdMw6VQuOnKtws9mnrjOftTwxbSP\nl3mUJyaZmfAvR5qhonPl4jA4v7M1YE3eEF87PRK0WwDNFs7e1dHow9yck0kl\nfv9KW/GF6ypPNXqzjA749iYoejqLP+LzeACcePq2I6JlaBSMqo4SMXMPbyS0\n5rHenuSt0p4UgHXlQlJtqX4UcjfEFmzYgXZHqF+7Rq5fUgNHLrPZ23w2jn8n\nZeZsC9cUxvMYYCxdG3hJo+eIwJ7XHKUCucNxN7sEpTpqdWgVIF+gFNC2EUN+\nxWRRe1ZGl8cti8ZvECD4l1Zl+xweHJPbwY/5Flad1mye4N1WhNUVuZCNKSMF\nqCW2WrTXgzguUEu0sQRE8OudGPJAqtaNFXj2AA+vIOPCfgmGKkjHgwB0SIcE\nVry7\r\n=g5Sg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5PJjP6my6W3j01Re4zFTWuXbSxAvrHVqZUgB03UB4tAIgS00483pz1JIS9xJVjJPzbun6Bmi8mXNovGgvGFfry7U="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-beta.7_1554092925135_0.8851907648703334"},"_hasShrinkwrap":false},"5.0.0-beta.8":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-beta.8","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-beta.7","nornj-react":"^5.0.0-beta.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.result()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [if](#if)\r\n  * [each](#each)\r\n  * [switch](#switch)\r\n  * [for](#for)\r\n  * [with](#with)\r\n  * [fn](#fn)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-mobx-bind](#n-mobx-bind)\r\n  * [n-mst-bind](#n-mst-bind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n  * [运算符](#运算符)\r\n    * [a.b\\['c'\\] (安全的属性访问器)](#安全的属性访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n  * [开发新的表达式](#开发新的表达式)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobx-bind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobx-bind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobx-bind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n  @autobind\r\n  onChange(e) {\r\n    this.inputValue = e.target.value;\r\n  }\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobx-bind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @autobind\r\n  onChange(e) {\r\n    console.log(e.target.value);\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({enforceActions: true});\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobx-bind$action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`修饰符时，`n-mobx-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mst-bind\r\n\r\n`n-mst-bind`即为`n-mobx-bind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mst-bind={`${this}.props.rootStore.testStore`} />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mst-bind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mst-bind`的其他特性与上述的`n-mobx-bind`完全相同。\r\n\r\n`n-mobx-bind`和`n-mst-bind`的更多详细文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/inlineExtensionTag.html#mobx-bind)。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-beta.8","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-9nW9Vnwcb1kHf1dS7ZruFGqXZXNsJTALArgAzVvp8pcH5NLUUO4VS+t3hf9Xia6Dm6OM+x5dRef++SwArmmZjQ==","shasum":"7de53ae4093fd8d2ed0b67d0a65163cf820373e8","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-beta.8.tgz","fileCount":12,"unpackedSize":49617,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcoZZlCRA9TVsSAnZWagAAdnIP+gILRfF38fJ66FpZnC9n\n8Qfo/JYliLqM0ozCtQ9FrwBP4prrd/U8I7iYofPAZTzha0O0PAGUmmdn0UZA\nFxmkMOf1XAb+zwYkl0Y0sOI9+NgQAcATxKOvTap3XTJA2oMGJLACefpuYE70\nvdnMocoQH6zMRX1mXaNZQBxQKq75DEnxEl8enMNCt5fXufCQwWfC5grOJaQ3\n6hBVUy0wqjr8RK6M1gVIN/eji0k8gfuReeXSWxgjK13PxgJ9eAgCzFZl9ZU6\nPrIHZznPqC+lcxWQsnDHKQqcnGuwweu+ZuwYwh+X1dUfx5JFtHm7HmbS74fo\npKbQg2Mq921ZqRWI/bZA9WG4YMDoG57TQqggpA7nxgAN9ko339xWI4a/3v8w\nBqqKE2wAmmOf5IY83slTpZBYKYvcQ1VhaQlSyuXAmNfHM5+V61xbAmh+R1Gb\n1TWxoqguth/Zg2wd0lWtPlAgxVtNpdHJ0W4sMH4Wfv8+AZt76bKHkl58xvQR\nEz+ZjV0AIXqC9PlpRQ+vZgmQulTq5ZeKJrXiofOn2wu7naPtF/sNFlak7mxm\ndKaGpKH52njG90O+eJhDVybM+EFDmW5mnutTwMrwctv79ox55xEojWWHq9EV\nk7FchzQCwssLYzfh8xBy7SF+mZ+NzE7YtKF6bbPjVIbJOWp5GWW5Osv+Z5Pk\nxF8W\r\n=+rF6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHU9gfkH/GZGLsTQXUFxmbQ+oTNnwKuMQ1qWHy+hvTi0AiBS3iQrgd7FVI35FI3uVsadZNRXamZJqVaODh1BsaIvzg=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-beta.8_1554093668853_0.6275667310829809"},"_hasShrinkwrap":false},"5.0.0-rc.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.1","nornj-react":"^5.0.0-rc.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each](#each)\r\n  * [Switch](#switch)\r\n  * [For](#for)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [运算符](#运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.1","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Z/6REvNXxGb5qj00mUq/VqXxqo+8TtXCrxq2UT70k1SrHPYqApaCNpQfmV31SdCGu/ymvVweXi98yFcgvBZF3Q==","shasum":"cf25b01567944dd36649685c75510ff1df95f5d2","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.1.tgz","fileCount":12,"unpackedSize":49823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrAXVCRA9TVsSAnZWagAArBkP/jGMpaQ5qswjhPOvTFcb\ng2bZ9oD9KwU2KPS4MHd71dXjwVd9t9VndoPi8Ypd2OEQxXiplxeO/nDwb1iQ\nY0C0yGR0gxkKjnwNMgxNrHH4S29U7xNx97e/XsYtXwdzlvG1ZafIly59J2Ms\nFqPJpAnAOpPOk8IIcLMoOCGcUjboe6VsyW6dr5jbACDwarc1BpJ1b3YQfuJT\na0EulD2jvfW805N3svQ7O2uIGkxMInT5IoZQIlZI/rXj743S7AjaH8QF/KOv\nY5vkycplt0GTv9I9D6EUsu4fwQS0KaIICdBNG4rNY3lf1Tdzi5y8yuPHMF4r\nWYxPxyUS4SRtWqfYgqoKWiYvMl+i30Mj0rtCtp4buffrzoynXgo1zgOJSkk+\ngs4+gXNK3V6FQ/XdTqghh/fYEqK8iuAyL9Aph5IRjd3607IgNo8+AGs6l/JC\nZ2EmLpTGIRd8GYlSg1qBFA8Zzn/DKeO71vFr7fl13WDlruu4xoEL24XV7Mnv\nsP5sY9ReyHHeejgvs7XuNb+7D/EWTE8Ol25swB7+n6F+rnP5BYgat++lS9d/\nppvHM7kVjCzCKKvDf2kFWCr7M/pG97CjbWYtYugxpFoUzC3UPujDH73YHf48\nZ2/kAuZn6o2Jo+iLVrLXWHluKO47TT8PtDyoysG5HIeBnfXJaK+CjdVlPBuL\nSz7C\r\n=jSdB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBmZ41/FWxWuKhu4hkDqZNueNQhis/qBCAyaJKRULk2SAiEA9J1tsfXpzKqPLmirbxK+IhKUBfmru2yjgKpViGhiCwY="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.1_1554777556374_0.8109137869425314"},"_hasShrinkwrap":false},"5.0.0-rc.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.2","nornj-react":"^5.0.0-rc.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each](#each)\r\n  * [Switch](#switch)\r\n  * [For](#for)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [运算符](#运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.2","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-+i/HJ2SS3gmbTM00mBqx/LjM5lskOPQ+YEZKDR3E8tfpruXyfh1OmP3jGJGVXq0eQlVXo3f7m+9aAUC8HAejFA==","shasum":"a5d11f2d11e083f75155850dcda6655c8cf6fd10","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.2.tgz","fileCount":12,"unpackedSize":49823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrAwSCRA9TVsSAnZWagAAj2QP/RucPCMNdfbiB+tYkEPj\nzGrfy/WRbhaBswNTOduj811G/xfIhHOIGu/tohcO1LRO9qRYTGonP2rcdJtZ\nfG8xuO8VxQUYFGZJgEn+6vtaIFwFpXBKhaofWE2S60J3253SizriCswt0g90\n3wWyCAws+M+rpcq9pnNNkaBX+W5DzFlDcDI1q6/1MGjLB8KMWCxtsVL4Dcyx\nsDZGZNsSbs+uREfJVTDt5xG3+DzzB8d9WZVWo42+hcAcdEU4iPgeumPc7E/D\nyGpj/7ccC0uryYWRv4kf1iTeWPX9duOaicfS/0Usu2g/mjHaf+L74/via+si\nsSNRIkddC3ryN9qDgwR0SvxVVc97hyE2nqhkvyD5K6MacN14vul9EUZNN5Eb\nY+W6aQvaL+5mmLb/FQe7sIUZQHSp2WmTNs1l3SM5eQzgvQ1392ArFj4bnnQV\n7Zqq/O+xiS9k4bYYOQqSIvpohTv+cOLTP+nqIWSJLADkPS8lowA6aY02vhSn\n+mpMz1ZkT/TR/EfbVtpuAWJrWa1IujxPoTyp19SUVLPLHK6VnVHrq1nqXPsD\nchi4fRcFrNPQ0wsmg/JfePTw/XWN+/D0/eUFK3nBlNcqIAa0xyS73D1KzeZ2\nBvDJUylLvyHN09AtRQzB3fO9wl1EfCWl3TDp3nNr9fCacAk+h4tUHI9H2Ew2\nCevn\r\n=YPFt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBB0CasIMURnbrhx8uno9Of2kpDcWBjdguQgbxI0hr4qAiBYSA+hO9GQBYOytTUMl/6xZhKkXASmJRZLDXNC8lgZjA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.2_1554779153367_0.1982999563463841"},"_hasShrinkwrap":false},"5.0.0-rc.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.2","nornj-react":"^5.0.0-rc.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each](#each)\r\n  * [Switch](#switch)\r\n  * [For](#for)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [运算符](#运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.3","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-0kX+md9IZ3U4WZZbH9bmrdpfZme9rSc1SBJTj8zzuX7ZdZ7PiXEHmf5870pVxqZsp4jdf699trwq828Glvmtgw==","shasum":"98e59e9dd6fb650c02d890a227b487690bc235ad","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.3.tgz","fileCount":12,"unpackedSize":49863,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrBCcCRA9TVsSAnZWagAAEF0P/3IYTu9KqxEETbAusQHy\nqgCuQYTyceoHw0movuEWea/6KXmTnIjycNbWsaH2P3GFfeZvLjISO4wHpegG\n+cyyUjW6U9SLl9BaAhkkZk1ng5IxLUMIH+A4OChR9qASSdMegWjXgacUEput\ne9X8cfuYFkg03sq7pPwK3/4ElDSh5+hSxp78Q3jSBvD5WPfrCqVG8VT1DOhE\nFYvkZ68Cvfy0QsdyDdG1lqGSH47ufxoeDmLoMsJD4nyxSniTEUcdI74Nh0xu\nw3ERyaeNGeN17KDYSjo48DqnNWx7R9pDMI34ktdbhJkfLsyt6xDmpqcNSdFo\ntMYEZIHDAXgLdyRAlyoXfeatGfBQyhRmo8HChWg2bSvqiLxVTj6d92DS/c7J\n6WHoTD2+A5xMIiP023pcASrxDJx889MNrc2v9G5+XO35KgpwW5w8AFNw3CwM\nkKT/yhSmzmBVeV0UWbUOz3iC7KHNG2oPnlgNtcLnjnI8FU1UMvBQzDKeKa3c\ndnS/DJe1yoJZ5U6ZzrBnrUCZTIIVgaJK6h8dY/3CDKQDptc4JQAuS20M7jdf\n2ifmsr+0F715xTPK+PubiswUds7kMMIGfIFbtOWExMJBZ+vugnPHkbdiX/WD\nieTj8RfawlDTV3javmq4e5nlZqeSToCZ/wLa59lV8IeAsGnO5BT7Giy8Emg3\nLRMI\r\n=a0qz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCrU9WhSC3WQMYRQp7YtqG7bh4L6tnUQeH1UFGca5lNAgIgK3tMTFvlur23c6TnWRW8IcXeFUNjbsFP/SKm15jQsSk="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.3_1554780316100_0.688819547819244"},"_hasShrinkwrap":false},"5.0.0-rc.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.3","nornj-react":"^5.0.0-rc.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each](#each)\r\n  * [Switch](#switch)\r\n  * [For](#for)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [运算符](#运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.4","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-es3dPqek0uFO7OUeUunIFDhk6U4bjrXV13OmUpJuHXSx3PxrfuM+v6UGoyHYv2JgUKSpkHd8qYidVc02d0aWJA==","shasum":"1f2e9195d842f6478e6349237259861c1879fe17","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.4.tgz","fileCount":12,"unpackedSize":49863,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrBL+CRA9TVsSAnZWagAA+CMP/jvmS/KaNefdcK7IQPla\nifFV6MQktbd2X6rmioNiaDNc9mWPAB6eczk2icmedhd+ydo4aZTF9DCgXkEI\njQEP+UhHhgp1JCK9u/O4KUC5lA+gTrwApQqlh1ImmI75YWY9O7Az7MeDRAPP\n4/aOOQpdjhp4m27zBfEUWQf72DqaH6GUCSlEL6RIt3NqN+8j/7+kTALtirKL\nzynxicTJiMjdFEsYmH7IZ9nnv6IijPlrTqSeFdDBx6enzYKSj2hKuB5bCJTH\nXLYEGyfL1WQCJjjcxLn6umO4nW+329uqAHbkcr7Mfy/1h2pEYHpuCyprH8uY\ni3eS5GuFakJwkvAAjiaF5g5yY1V9Tmn7k33kJM1DVCaPSh9RekyG43KBaWdf\noMADG2ksJ/KEbgYfSzOWQqvtOFOF0On7BsdtQoKY6YFHdDgnLB8maj4l76ci\nE9Ri49Vo9RajDYByBWWzXyRnb6o9AkSmjq9MirgFKaDDMTTVXLUwkNRDQoWr\nVl+Z7YLhN69rPbUc8MT53l3JURYnGx6aOHsQjQjhedwXog2t4Mca5MY+CcGu\nFBWk1a9QGpyDCZUTVHRBx9X45EW0g6K2Jke8fSi+17QLt2A+M9E7nN/Ecllz\nFuNILQr+sNreueXoMYRgCrTdEgM5PXTGt1i2RYsfbaEkLPU45o5EuD1pbqx8\nNdld\r\n=eDOv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD88vIbiBBnkriuj4CXlyuWNel3DneYXNEZG9JZh8XeYAIhAMfzt2w17TBtq+qhZqOJlvJqpsunLe0mSxQnLpRCsdH/"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.4_1554780926268_0.3654046020894417"},"_hasShrinkwrap":false},"5.0.0-rc.5":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.5","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.4","nornj-react":"^5.0.0-rc.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each](#each)\r\n  * [Switch](#switch)\r\n  * [For](#for)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [运算符](#运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.5","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-d5DQ+HaLgqwiSd4V2iKZU8cZRaBlExccvS13ZHH7Q0ON+HxFMsuohaG5ZcRq77bA/YxtwRg9SZXz/XHzKrF0UA==","shasum":"4ac8f81e92b55192faa2fb098684d6b67b6d83f5","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.5.tgz","fileCount":12,"unpackedSize":49863,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrdr7CRA9TVsSAnZWagAAHhkP/RfH4Ib8zUcRBUWisEcj\nI6AJXBqNlhrTug4Q4dqMTRT4b/K5ZtKTK1sR7L5SfAgW7dPnl6czJ6Mms67C\nUSVBO80NoHkdvHewiVwCEFkAiRKul20bcS2tptJaPsXQOxWHT6cOCTAZ4IAF\nG+nqzIUafuVawHcLsesIRrhWm/LlWsSTRIdeWLIz3C700NXKKV/KC+ruiXjH\nhI0fhRNcKUeDfgUoRaXG/gBtf8QGuLpSuuGpLdNfGMzqWgJ7OdjGEsSjJjRp\nMgMj9heBomuWcql9LWSeWFeEj6P2+tZVw4lmoIPoy3p47XtmH4UTV9iEMx0d\nWHbtfgjItKnLWTslHpP+e/fFgvfX6lj4EgS40BGGU2mUEpWrHiW6GPsvvPB9\n/cNXCiIe6xZ8Rxv6X7L0ULp4wYn8uCbcRerlG7YC8oCCpI2FN0Yd+xfagAo4\npxYZwg1ksam55PqgwM1qCPJB4IRlzM9Vkb5DXPDsM8pEVYxmFZSklgFWSkSh\nk+0lV6kXXTzqR4IKYy/6CkKfakovtbcQtzFCtmTgqBJ210rZrdry7lzHV5QP\n6labanzFUiDgix2e4oeawe/ZTKRSDFxv/g8YX1RtnslSOPvDk3E/ZQ9XtNql\nicPBjRyDn2KaPc9693ez5yJf4IL/u9jXfHNjegHWYf+HWFTea3FMZ6R6I+4w\nUxnc\r\n=mrOZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAeRWAQpwQ4GuZXNHtP6ZqT8HcufXUeAUM9J42Q7HPphAiEAsJkD8mlQSjH6/bPlw+nMKPPIYEob9OzZMR3wgd4R9sc="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.5_1554897659316_0.4067181039633838"},"_hasShrinkwrap":false},"5.0.0-rc.6":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.6","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.5","nornj-react":"^5.0.0-rc.2"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each](#each)\r\n  * [Switch](#switch)\r\n  * [For](#for)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [运算符](#运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.6","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-bAVqATLx3bsH884h87YhpVAKTrrjWNOFFxTo2+DjpijSixvsm8qN2nPTE+qSECLVpq1NO7vkE3rqsMPuHGTdlQ==","shasum":"746580477f8f70ebfcd9a90f8eeed819d8390922","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.6.tgz","fileCount":12,"unpackedSize":49683,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcsxraCRA9TVsSAnZWagAAwuIP/RrOA9T2LuD7aSPyoY/T\nxIuiFToY5GhPEqqBQDVn4KWoUpHzRTrGL1CVy1aM1yvyEao9oIdSHq0iXCAn\nG+7QTc/EpTi9OmlR0Ztz6QhS3xIno0+DVLa54WvjHT3XH5GIa+eT3bSwlQEU\nEiLxUcSfG/QKZIfgxDsBunJXpr8iohny067HHaCBkiVmwqJMZKe01GAkdae8\nWKCGHc7NFVGtJezptqPskoNDCZGNSzTS229YuGolODrnlplXIXr3yXWTcrH+\nIrgggu+ihP/vldIILz1okPBoDHj8UzW19RjdSXaHFUdP2XcI7L5d+WPTpj0o\nNuFOOhBxdTFRiZtuAjub8/mzaAi9El8CCraulxoMqSRCAKG6XGlcU+LVamyz\nLcSJB3TzY/8G9gxDtWobEkxi+PIcHYHrK1OrwOYFpZVkLa+MP7E5sjSKFhSA\nlHpB0IlVxUiCC9XPqTTt2MfwENBcZUNMmnNPCGZHTWgOvjDz6wweVx2s+QGt\nK7eBMsYP66gvH6ESyJxik2g1r9hGXoaEG6GQz+HZ33l3wG+Myf2X67Ej4Z0n\nXD5WiV4WZ26lGQLaHgFFiuC86EG8XgVR+DSfr2UbazQhZwk9hBHDaCc1+n9E\nRFRJYCSyqhgnzaO0e0BsGPBh67KFVLdI1q7SKMtoh7fTSCFoYMtYMperTgU5\nba/I\r\n=uti1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGVTPndlV/U4uPM6l4aDzZVtajkOXZCGt/JWJZEsuPJkAiBNwIY/ex8zwZ+dvyWUSQdDuuwJZAUoLbX1jlbMWgRR5Q=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.6_1555241689987_0.11291524929966967"},"_hasShrinkwrap":false},"5.0.0-rc.7":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.7","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.5","nornj-react":"^5.0.0-rc.2"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each](#each)\r\n  * [Switch](#switch)\r\n  * [For](#for)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [运算符](#运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n`nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.7","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-KFUK4lCt3j1hBP29mUh7Qyfc61j7kHV+B1LwHTWbh6+vYlbB+afme7iEwJbsQKq/nUaZFWOma1p2rNoXvRpxxA==","shasum":"ee0a9dbb241f5626faf8bb1edf8ab7c985446ba5","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.7.tgz","fileCount":12,"unpackedSize":49793,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcsyIiCRA9TVsSAnZWagAAbnUP/3jZTnidY3A9uAB9CAfj\nuhlOpI5YOXqltoY9CBeCt6+ya+1WSzjsuFKYwtZaE9xeWRSIgh2yeoOMR3VY\nLVSJwzn56p3m9/cnxtCl8/HZdWb8OwE0kw8fhxfUZO5ns5t+wnJaHBwIvU0E\nAa6suAUqSyQbc9bIXz74rhH6hGAei9XvF4VPCo5C+OIsrlHzNna/2ZJ4ddfz\npxaPL7Z8p55KK5Ab647MW+WO+fRfi5fdNL/IuWIT8ndsXYynbhQ/zOOEtPh6\nTrre1s7CbWi365CAelteeiFGJYMtgrC7vIkkkBw/NyeIVufuLG+qjb1/6AUr\nqQS+eVdbyiCMl/YomFmBQpjORe8SnX8PULmr1McZuUg0lBQ0ae7hEGnn+EUE\nT5thH2zl1Lmwh1+/u8ulu1lX7vX3TR7fw4L6TDjFkq2F0RHaJXeT9qDNT38A\nodLky2FK+SocBuRvpj62n08PLQYWhHhEb2rX9OHHKfTLi4FUxRMAcPNBAYA4\nz3QpBzOOlDGDpCnOM/gG7f0GprGptUMIJ5DR3pDv5b0fJ+Bh6Bdo5atxSY6A\nOihYpTyZBRD4/ArqdBwLfmCkMzphsJkwv73MJ/Q36DW8o02iV8siKweR12qK\nFoyVV2oNQ4wb7EPnpDq5UFwYvoM3NmQAjS2Xc32P8SDjhIcO/EK7iUuOmAwe\nfSBG\r\n=7VDM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqtXE2fnFuPEUzoEELMul0mhyxpGqrAlM+KPXLkZkOkgIgTuBPST6yt/2laVdeiXhlJrXG1sDBmGOTiCJjYp//jQc="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.7_1555243554044_0.8563650894895414"},"_hasShrinkwrap":false},"5.0.0-rc.8":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.8","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.6","nornj-react":"^5.0.0-rc.3"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <#else>\r\n              ${<i>elseBlock</i>}\r\n            </#else>\r\n          </#if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </#each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <#switch {{${a.b}}}>\r\n            <#case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </#case>\r\n            <#case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </#case>\r\n            <#default>\r\n              ${<i>3</i>}\r\n            </#default>\r\n          </#switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.8","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-77R9w5A5BunH41R3YeKJbOQ+EFuTu8gFeAqUFitDHEBTPiTWcDYuqWVZ5nC5oLHloRxG98e+2xg12U6DCh8GSg==","shasum":"34c7b4a2247d08f74e16d6589f8b8c3412c7ce18","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.8.tgz","fileCount":12,"unpackedSize":51826,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcvS72CRA9TVsSAnZWagAAS+oP/2VocWN11c+G/tT6rHlA\ntHktnRlkmjeoUzMZXY8Ln0gQfaJMrUvRSVJE5wUGSV8JSGJpboPmcHuslQrI\nlfPfj5Lx+P6p6jTXY8eEyFxvXf09b9jrbV1QE4GmDvradjZFVKS85bWfgdwd\ntC632DVWRU2/MK7ppYGesBd24Alehjs+ZQ3YFhpPqYqSgDquJc0tTsOxW9RD\n8tzMFXVrB6w3EvViwMYsuAH/EsnfD8bTWhPQznvc7opZjjfkQcsIXzBSy3ml\nndVTEt94pU1lGOKB/MFTOz9sRGFOFVoorP8meYi4QJ4PRExUdotERyoiwWRx\nxf/CD5qw/IuNgwnTof7qi+v4/yenL3egmCszouRtOdVt7p3+prdlxGqlbt/Q\nKl83LDKsVuUyygVnFlGPabN04ZzSeRZ0jm83m7q3Yqy9fwlJEZoQgtF39tP7\n1Mm9CM39bKMVK/FnVT87ygqpVOyIUFZgwBVLJ1Kq1EPfTjaoYE26Hkx5whNW\nZl4YpRqmPsrhK/kXUGUaH1uP6ZhLJVv9ClH0YFzFj9JxTUgpds1yLPG9QPoe\nGoRzhNmJJH5aAVQ7m+4ufM0nv7LEJWS6PPtE+5+Fb5jbPz4fVzkmr7/MTaE2\nt0WaVfKiafx7qAVzQ93RCyufqw1HlpQo2M/YXRjElSUxd60I8rxR925Cj2SV\nnkNK\r\n=lXN6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRabBS/1QYGlqnajkVhkSilaPOThMynvrG9/KaX51NDwIhAI9MHrT9IJIl3vxoHGeQkMnZMlAZOUt5d6bglo3fyUsp"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.8_1555902198186_0.6276625155492221"},"_hasShrinkwrap":false},"5.0.0-rc.9":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.9","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.7","nornj-react":"^5.0.0-rc.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.9","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-VXvGn2nP25sYGd5QAxwRKGLHuIt0/iBP7kJSPOb3ccOiFhKuEHt+24zekOQHVwAPqmRXflxe/341o/BUP1tmgg==","shasum":"68ed8777278bff7db1eb5b0e1efcd4bcc54d546c","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.9.tgz","fileCount":12,"unpackedSize":51820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJczmGhCRA9TVsSAnZWagAA62cQAIUNF7XeOYZJxVYCJEh8\nFPmJrDhd/KhBiGFmejBRkTmUyJJ7G39f4Mpv+b4Wda7wrsftkltUJhkoxt4O\nDO23GKHUbW1/rKR2oqC/zx0TuXAEkBuBRc1W3zg/+B9igbDeWk2DiHhrYxwv\n6JXLXyNmlc17uAqY82eYZ5iR7+2mOShPFTvPojI+OO1ZU/VjDUuv8Et2l4hg\n2sYT+H1sc+guYduBmG1GYNR7U2dDRa1wpnkjTztUSi4Agh7j6sOKNlR8WioV\nzJHIkid/h5Tma8lwHiQ8qbwPYCrHsNdYwfl9ur40D/Kozixq0oVRkqk6ems4\nO3USeoIgTw8m83zyTg0pstV75p5bseuiRKc+tJQk2ANr7Duj4882OyjEOgYa\n7qiiBLNx3jDVJd2Ztp0ug0dcwKBGZk/046yJscuCQRosCNd7AVM5Sx3qZVg8\nxUoY2deIz2MryKX4f38ut3ZSR6szoUwoEnKDU1mTrmlojbtf6xDnwI8fLZHq\nevE/q5nD6gKg9jlY2FrtSHt6tosrNFB/j7QJu1kquaO/T9W9CMHwaXvvlW+X\nbuXjZVs96ROOhelONa9CN8EL/ixJP8c1PqGcRA2lDCY4nGOxYEOyu8+VHQ6Y\na1UTxC7z7pKczdRFctqFaPYSaJSMHJg8D9WiEeguwe+M0cpjd3UmHBuZNz5i\nBoaP\r\n=dQvB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8OF9RcxgIW14VsXWlaaUIVhLizYdsNi6wO1dbSBnbvgIgG8Vtg1aAmehd6JfkKuETb4f+ccHO5RVNGvBxi5ntjXA="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.9_1557029280950_0.11185288013404437"},"_hasShrinkwrap":false},"5.0.0-rc.10":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.10","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.7","nornj-react":"^5.0.0-rc.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.10","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Y8BGw0tVvR2DEOVGqOp4kC5cthBoNbR4GDP8+pW3jB3cr2WmN7dR2Ehqb78scLa+z1NWbmGoLL30jFICa9Vjsw==","shasum":"7543c351bbe5ac9004fd144b8621c4e0e0422795","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.10.tgz","fileCount":12,"unpackedSize":51821,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJczrq6CRA9TVsSAnZWagAAb8UQAJaWF9WpaiYQuplD1OP8\nR69Z6q9+Rey5wXxcQQu9u/AZ2zrvsPe1rk2aCEB6fVSLWR9Kk/iv4Tb3o1OZ\nDEZiFJHWicv2cdCQ3CWYkBXWggKumeaTHUJY4CTGA1ou3Z8Tf0fBPOE2eSSh\nToRLA0ZaOzKuPGdWiWrrPsTfWzPld9oYOyz6ryK/rYqBdutO+ZwR2fwyKXdq\nKDG5ST+L+mxdjFsrmmLsnIVaOwN8RXExRuRCKqnnDeIYx/J4QELFV8fUcnam\nxdzjkw87ZvUIEgHi3uCliELc79TG7jvPeVtE8ZyYzETy1zzCfQ4Fc0VeML4o\nFs5WeJPxapw4+lbXgFnNBTMQhoQauJx4cRyYCFce8FiKvZL7K7ZTRCWBXSe/\n4aRcQXvk9eCswRRk3QZxVOwYQXUZ19zrsVv5EO7aSY24rsqyHcytwPo3OHQK\nUKzQOYZ2H/CSqXO8uEZ/ZaE3d+vPt7w20D9+HM8MkT7fGMrhpfgNA0y7pmV1\nID5rL3gcCfzdOvCOzBQvEA4O4/xTg1DOLLT5JmktB8/0qZvYMNU3+VD+yiCJ\ncftmCGiCVvHB8b/JghsMUC8Lp0L7cEbWgFR05EUmzQy/9zQ1ocuHjT9RNaYr\n+3yDCVeeIFhdb8LDAaxkOR1B6nEc/vF3nb+malZzpvUUcNaNHHRKPbMB6bVB\nQq4x\r\n=M8L/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHa0BAFNRiKCZZDrBO/t7yfUHV603TGHaL7ZJo28ojPiAiAz6+xX/VXQeZuPn+aubAzuTCkyyHi6cQzAUBgZVY1nuA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.10_1557052089331_0.3946769038915563"},"_hasShrinkwrap":false},"5.0.0-rc.11":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.11","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.7","nornj-react":"^5.0.0-rc.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.11","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-xtha+w77ckAfK/a4d4f/z4VdjNR45+7+IzV47Z4X8IhHiynbXIX+t+66CAlIpCouTd9+qFH1nAkdbgW85No6qg==","shasum":"70277496bce2e11831645e25e9909155f18afce9","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.11.tgz","fileCount":12,"unpackedSize":51841,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0A82CRA9TVsSAnZWagAAvD8P/RHCP79r1JY/i3FgqVhs\nVxClYscv7b8fZbGo20pvyRTub5yErKUjIBBNW4bi+PPz94eYzh+YMHpgDvuw\nyoHN5Mz6JLR2tn0YDBU+THB0jrSvE0wE8bM7RuTPXbNPLxz0WvlxK370mga/\nnoWMrKFIBDhg6kTYfxDecN89dhlduk7squHiUxDr4EYBHiDf4R8oLj3v81Oo\n87dWCdNHLudku9eXEWt3hTqDc+f9PmuodrFMTrk0ZzA+DOUH3COJCM7qjo6S\nj/m2wSAGF9ol4ccyTrIdCbRDimQCvgUAIDX+OGBMgyyQ0OfrqiGFEMdwQKfD\nnR8fBHIwRuHZJH+PhhrwuXNP3yxCg7xz44EwRZX17FXf4C2Gp/p82prpqi8S\nj4GpuPWJEgQdnGfOvXHsn6990VNjPvWT2E6Dk5StlZEuHxkDdkLbHKv+vN0Q\nXKCScf02OUgl0pDOMPJr0Exf+rl1e3bXc7uKB53rCfpDe7QkBVRMWw/NyFaQ\n10zw+bFeAPA8kph3dShBp+uVCwUzKiALReb6KHK/82h+aNHzCyP3rGSzNFjk\nhLYrdd3e/nFL6fhAuFh/MwIJMBtPStJMGc7vN8szaEq72SgPvEBt7wlsT6KA\n+xvqiCbrV8m3URyDdoVAUzR65aRVBwEdWZPlhkdHe/mD4736GU+GoCdfewwG\nBoQr\r\n=yDHc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDcumPm9m1aJgUwk/KHJjL/wbJsfcYXh54u2vNyPBJDcAiEA8mNoL+H1BmOJkb7i7FJnR8+QXoxfEKMztHK0c644UMk="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.11_1557139253646_0.1961716891488121"},"_hasShrinkwrap":false},"5.0.0-rc.12":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.12","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.7","nornj-react":"^5.0.0-rc.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.12","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-MhUfwuvwSvD/dXqKFFN0Szgt+jkyC/IaVvsLbg6e3G2uYA5/xBhVpu6esVkxNDYABJ01bA26mAf/ixtRuQLHNQ==","shasum":"1963acd07fcd77c1c788ffcc8deb1cbb4634de20","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.12.tgz","fileCount":12,"unpackedSize":52025,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0TRECRA9TVsSAnZWagAA82UP/0TybviazJJ7oXtkH8g0\nU+Q5+7Zzrq8tD01i7L6oEd/E3wUXlUvmBtBRk5iVXWtO5soPrSvCtX93/FdW\nunVsm0zbSbfmTOSNRUQRKLtz6C09yTy3LtFbQFmZ77BMqyN+g9EoPqUM6U8U\nd3i7SYnWXOnz8Igdm6Otupl1rWimmq0f7Urxu6+q73YWL0pKcMIoWBRHtEia\nTvkCCERnj+ukgZNIPZNPH555f2l9/Gteoarq5G/0AeEe8tYWv/Nv9yaipq7S\nky+CUXev7TQ/0UD5YlNSLb5/ghXpN9fA9D9dskScMxVfq3bYuiVbZPMrHktL\nNIaEojkQxMfPAQ2ar3ynQRxjQfCkmddBSgdBp6lyqfzRHt7IjLGpwowu1cyb\nxD6TNX9N+FbAZBaq6bdKuXU8tgFmqS/sZJq5ca7/vv6gw2Q3BFajwX94U3Mi\nxvrZOTjIua+J2N/QZ/cL43PFbhxSK5HCxfPGorJSA8ovc34ux3IVUB+j/72/\nOfPnJnMmMnIADwJ/lxAZj5G0nYNJYSTruUbW9rWqYd94lBHMUqkhFadcPw9B\ngOAcZ78z0cLGjxFttOelbGRNY01GXvh/GhQRisfx71fW85JQpSKOdn39q+bu\n8XjXVq1rxAG6Mq1d5wsRa9Orz1jNACyLI0edmU2zURHbnzD3wNJLyImR5aiG\n+YoR\r\n=IqTr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCr2oJRUVOtHHXNhJru1aXiQuXjFIZw0KUmxwfX//70gIhALKBWOwD7fEsqONHnd7/3vtlv0G8NNEAtmm+PvSMXp6C"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.12_1557214276012_0.5772867199259282"},"_hasShrinkwrap":false},"5.0.0-rc.13":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.13","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.7","nornj-react":"^5.0.0-rc.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.13","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-nwGMzjmQ8Rd4Cxw0vsk+CEv2pR2cVx29N3OGrBEJFEHEjRm/+NtOkrL31no7k1CcgNr+M7W+gaU2W3yrtVU50w==","shasum":"f5b7675043105e185b1e83b56f801102cfeed319","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.13.tgz","fileCount":12,"unpackedSize":52039,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0kn2CRA9TVsSAnZWagAAXnMQAIQQHmrEil+G9+uTVr9I\nR7UCSi7+mW4RocA9QOkfy3C1bpKS6k9n5MJfDRAeCSrudqqMxgHZIrIyt0C1\n5sXsXAsL8ZriMPslr8pc6IngMhv94kcwRu3893BTXusIbo60Nd9fppapmJwF\ni6vLIDwkgsLWrDeqa0LXyRKVpQwETDENfKNYpl9BENJFQ8yzbmrc1gjoLJVQ\n8C1GYjjbBiQYUQV4Mobza4iLGEiSTGDG4WeQtCU/mLSBIyjlXrqfZkZx65js\nJx2ls9V9I3n2OU/AFOrGdtAm+UvTsOR44gVQ8gA73ao9lRxuaVTF1q7HYc5n\n20FZsB06q4hMK8Xsq0zx/5Eb3DjvF3KNSJraARE+SykjPbGtBI+5jWgEE4i3\nZXGA9MctCGucUTxTxyP1y2k2ZiDgWMwKD42U8o9c8KId4fORsWmloSo63hRL\nMoKbZJMWye7FVYJF9PQddSH+4oPiIe8ol9Xk0CS/0zIB3eEcKpUYpJ6nRt9l\nEDq+FhMyQBysJD2XerIJgWdkL1G9Uyu4CJulxWX4CgZfkZ5czxj9qvbVYIni\nP+eTTtfI+D/7+E1UuGRWwORXghGRBRy2CRWt6OCLMupZKi0pL1nJ0Nt37vXC\nPx5+zrH4HxX2eIrksG/+cRMjUW9DCsX378iAqGSh0sav7f2tWlrbbp1qrt1B\nHBHT\r\n=aeqU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcmhx7WOQF+KmhaXuBLQM2/spXov6B8fGXKIhk/JQScAIhAJzRQYRodqWwZLb40bvx6W3vygkOBiknxhN/KSUn6pJ6"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.13_1557285365207_0.6056651294883479"},"_hasShrinkwrap":false},"5.0.0-rc.14":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.14","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.9","nornj-react":"^5.0.0-rc.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.14","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-6vyF8MYKFMiEMGicFQA2qZI8x2tFybeWeLu4xVQ5S1t/JBQCW9pVFq2m0NhNodtfMx32jwAGGBRHPdKRfbNcZA==","shasum":"1efba0c50ec214c978a03039b47149c87d991429","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.14.tgz","fileCount":12,"unpackedSize":52039,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0lvuCRA9TVsSAnZWagAAtIwP/Rdzm30xCUtbOWzP4m1Y\nbJn1ByKyK0oJ2WMv+86/0jNH28Iy4lqg1mm9Ecy95tKgZCWJBPfS7xlZfhSd\nGvgdGfukEV80WXK22aNNDB/AzuFDct5Bz8TWyhZbI7rffjFcYPiHnXkiZyZH\nElmhRvZegRguNRvXWr+M5yImWwjPpiAtOySBl5O4KWz1ONdRloLjZ7j1u4gM\nWjx4VguqT7IeWGI9e3Z9PBmSINTQIw7Zq9y97UktvxS9Ea67qMbrR6YITPJ9\nP9+FC6VzTF5PzcMCNMaCVX9GfyTfbKaTB/eoD1P6jrqG3K+UmNkGyxn65Drf\nChp3PaZDLh8NYmvwj2S4yF+HbQt9bABT28MGUTeMZyNHqlAHapCWfkCa4uZG\n9N8vmdwCbhDYskdDpAIV6TdQJZ2XpoRFDpKzOaq60dNxuT2rwTapWZffxMw0\nqSAIW9llGKuqRrqswIshV1YOiQFGNOAlYPAPRmznOpJrGhYxPqRMcMQlrYoG\nh2Qr4kZxONwKUTZLA0cvOCb3fLLsUFUDFmG4NJPsKGSslHOZpw6lt4PLrqV6\n6fQl8jWRz76KFi9QJTa8VlLNZHUlycY9iAOQM7kMm94lFCE6Ruta7cgINxlZ\nJDQmS53uZNhhklKPtBJqI7kPvGQfVcd3dPmy4m8WvDlJ2y+ueris8Q0sOsV5\nLNko\r\n=+UkA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEPQnJNCGLD1JYy39vsdIqVrW9HRHFd1Saysq8ctV1zhAiBoaMWcM/GvJAqVr6lK5m3gs6LfzR6hi4GPA/ec6mdtHQ=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.14_1557289966101_0.373534525534432"},"_hasShrinkwrap":false},"5.0.0-rc.15":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.15","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.9","nornj-react":"^5.0.0-rc.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.15","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Bdj9Iz7+3Y2bDjhVpm1UuR+r7utNqq5Y9IPejzJd62cybLrjexUXdL+A31g4z5dAgJ06wmgi/Nx6t7ACvpEV9w==","shasum":"10fab7a318ff771443e329ba2667ae3e84730b50","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.15.tgz","fileCount":12,"unpackedSize":52039,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc06C+CRA9TVsSAnZWagAAcy0P/3eOKw4Ny9NG98DUmvnk\nT6j0HK5WCbczK190MfSjAH11entiZHIdMeRbIMrFN6+y5q7/v+uzVK2alqlA\nczjtR71uT9q/SXhoOr8kkHvCYPJLHRribux0e1ivP/v6EuLrjhRusPc/aNWQ\n+kRfAv530MsRD1lGVb8y1vQlzkWb9zFNxfavb4BdjecATZN6YcqXIA7Nc+wR\nqXK1+kPmCluE6XGBOZU+KEowTsBLJ8KCHIl7+8VVBU02C5wt/CqETZRhsX82\n1BzMFlb5OqALX1yXeP978qok62YYf9jRkMW/ffFd3DnuVIrQYpjUubA/dfRD\niqUVKyMge9ZxWGHEp/w+XdxSAN9fAlI/4du9uZo15ac09kg7NkdU//o8VaDb\ng4rpdZt7Wed+qZiKLv5TaDm7R+k3gYUhJ/xShq6Sgg348jDZhe+Pew/p/1Ti\njG2Qa/9EiIdsDf9sULx3/QGFCJ4YF8X/JDsiEOrJUNMyXC7OrH5r4gYyLG69\nW/MpehNAkyn5OKH3A9zfnDD1pX2BH+PcbipIQfASh/HUQk1ZNzTolfMHsZ5d\npPuKuO+qrlGoQVYJPjpz95FEnD9G0B5W/FhrwX0otec1GKLs6yQK9aIoHFHr\nEv//iq2xO7tCy3WQ5jcXh9w9Zqo1EKUbap/WJekgjwl4rJvfPVA+inBMaXcG\nFY6z\r\n=SNf1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYReHZsFbdw2KMMHCxWv8ml0squSZDKPqpFPDOuNWTxgIgXhnNopVwl9F+hL16LOwx3pq7KZI2wN9wH6prZwD6Yeg="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.15_1557373117326_0.8099195335273046"},"_hasShrinkwrap":false},"5.0.0-rc.16":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.16","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.9","nornj-react":"^5.0.0-rc.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.16","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-wlm1LqdVZ/EL+5d4ffsHO5NEwg8xV6BQREqnJZC0/1qC57CfUM1bWDcwYwuddS0ggusJZJfbRARsArFvJ6dnXg==","shasum":"ecb059ae0437a7c87d542d151ac96ed76a680526","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.16.tgz","fileCount":12,"unpackedSize":52362,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc07DuCRA9TVsSAnZWagAAMHwP/0Ouw5xal1HSclzMKznL\nfV/MpDjneDkyKWFXSOz4M2Pb1Svcuy2UrMo9MAiAxqPSmJSOugpkB73eGPrl\nGDCMgC3aAk02M0lGrtij517PT4aIj1djLSVUXxX2d3bWZxyPafAww32LZuE1\naTCrJEql2Viw/YqJKZI7s0SK99b3SeDx6Bq+e93DfJDltmmwzKF4xUP+q2iY\naYl/zn6yCYn6EGMyJjWXW/X5hiuxXHN6mEEgXI0iAXpFmONPGLB+I9IO0gVs\n/p/Yh9KsiQr7HvIb/frEQjFABIBJBSLbzPC6W8gg7TauC75edc4vmZLSKFpU\nq/JAlEPbpUGtwdh3km7f/g431XE7CU3Zz9xXwAX7SLWwebxMalZg8+uXakV/\nQbW/IvKbnxWXEp2WSmYvKY0k5WlLEnX6cl/gR2iiC8+VEM2rWao2XIHrx+rx\nG1vuzF+ZNeYodAX4chuIxrG63CTL17ZDD/PUhOJ+Ul6z9Q7BKpouarbIPyxp\nuRLVgspnWaZ+5kep3OKhuzj1fxnBpBmKGkRxDjcT+7VSXqepIEuD0noSvqhc\nZWd6a+f6B2X1Hw5V5oH5BZ+H1V5MIm7ETyJGc+TD4vVBkrDGx3XvCd+0YtRv\n2zcfXcRjqriSTa5rnBoSXVOvZHmNgE9jK5EEVLay9HmoFqMgRWeHiLN9eZl8\n1kTL\r\n=ww+O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVAzOZ/PsQj4w4QnuzpN24CoqxcgAnUBQoE18QW9t9fQIgFUHNOcMc+5CJJtMpK6iCRcXxbuh3eUGMsRKsBF16Jmw="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.16_1557377261672_0.0627340208934637"},"_hasShrinkwrap":false},"5.0.0-rc.17":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.17","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.9","nornj-react":"^5.0.0-rc.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.17","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-hcgGG1Ys2iaPs9NvnTsr91mfYXE4w+zntM4s8ULCELvNHdcC1wxS7nXsP9s2I39700K7sKIwiPf9rE7fYpiZYA==","shasum":"788b720e48b5ed05038cde16931e84c3bd50052d","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.17.tgz","fileCount":12,"unpackedSize":52400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc08zKCRA9TVsSAnZWagAAJDAP/1ZBYVd4KlqCY4c1O+VQ\nsTaodZcLNeCnQy3dtuCNDqAFI7ur7y+QMKaru2387I8pReIkDkcpx7kSaaDn\n8Q67CjbWVnBzyTxniBXwZY77nrVIYaoVrYCcs9uIHlkq+zUi4X4zE0m/h8+R\nQ9ygr+Gf0fUhWb8A2H97WcyHuJdWts7RMP/n683zX7nnqEWN9uvWGUHChct+\n6FariDAiVYjKsDqehG+dEYsPItFFJf/aYSwBurW1ZD5C6hBvOl8eJJOlfKvF\nOhkys4Jxkz3QrNfN2Fk1wdJqtAFpUG/zCtjjSlTrMKZXPwdf+K91br5Imw5v\nLO1Rw3YvsQ5Oqz1jGVflrhd6ABBYp50h6wSPBGyHjBmiszXnIpQl4GGtsxzo\nD0tvsCq9Jr6uV+zwVX3Pr+K7a57IYmEAet9bR9DBARS0zNc+2k+YY0O0dSE7\nU225Uk6CWb5XX4iD1UyWJtYF4LEJok2xHoVQHRSy78TT4fmvoj79EVMh6G+2\nsnQcLlYFOkzSIzhQZ958UBNWBMrhmD7vMimG8b7GC/OSbkxJ2qoP2dFZMjL+\nR4Pw1vnrN8Rw96jj/Ps7OnEbh+tK+/7hJH2nX0TWg6TlMwF/GgqXzTfsASrt\nDwo66blwKkHxpBU7fY6f2Fheifq/5rMWUZk20eo/Ye+UDorHuARnYzbGNzzn\nz7S+\r\n=ndL7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8HeWsqKU7qxrcFl/iOoS1hS2MN5Vdgvoevdi3bWN9IQIgB4VgTpH2Qpt1wAKg0fgEuYdQaPzHATs5pe3Q+WEtuYI="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.17_1557384393885_0.6081523419563977"},"_hasShrinkwrap":false},"5.0.0-rc.18":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.18","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.9","nornj-react":"^5.0.0-rc.7"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.18","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Gvp03JDAw0zdn3KU0VRn6fg3NOLMkS5cv0m3pZ9A66lpiY/nwepNARDqUs0eUDse0QsLuzUB0IILkiA7Ze1hmA==","shasum":"3e888b3f5fc3beba78a83776111a20c55418443b","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.18.tgz","fileCount":12,"unpackedSize":52400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc2oHkCRA9TVsSAnZWagAApuIQAId3EFemjXsTfvMHA/Lm\nbImVv0qZigkkjzOWczi0Ct1EuN2g6v8KC8GxCHtJ+aYkszfZBCIuBp9x76NY\nZMTwTwFFYWsIVl6vQUnfiMOTDo8ZA0MmqHvP50vJSA3jKXEBH63eaKL1VPVP\n3pAGQwyF9UZqWBqm3BrDC7Q3W2wKmmJZnGVBLp26jnxoQ43g76zPPVrk6Nuk\nVqflU/9epu43SsT/oeHa9729tLSXvRRu6ViJHPSOjulCnjv8e6EKN/2TFUlZ\nZts8xSH6z4kznq7jOtYI6q6SoC3OsOIPVk6an9tMqWQjlvq7XRXA6HisDTJ6\nt8eKcYD/V9MYu7mX9TImPAbsz/gDCN1QS8rkCfK0dTG7IS5wXzexj5Wc7z+m\nWyVr+VQaIS0e5iK1kq5eaMwGP1kAWL7yvfNxwFt01/FcbTYp1d0o6Mxv03+x\nAVSgpC3320HACmYVxcMgDhmZq96PoK2xT9Fr5PYIvHSy9+faANAJHCBD00II\nGaHr85WNPx+F/qRnl411o9G77lBOSzDqcbLm4yl2IOpXFHwz3NQQH/Kr0Wf7\nOWQniHeyj/GuQ61qeDrVK6BITv7COe+t3JzahkOZVjbiAi3v4rcqqAi3yAnZ\nZpOb2FVlmTjYjV7L4pdgGjY9VD87bUBa3B+gVpX1LqklqgpmSBvaimjJX/xq\n1eg4\r\n=Rimu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDgIr8WkY0p9yHESeiaSqcLdDcEiYy0lqPB+OgmwCncNwIhALM0zQ62KL5ej2lXKo/mzKZOIrm+jDfFHQZAD15XYulL"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.18_1557823971675_0.24082206359243297"},"_hasShrinkwrap":false},"5.0.0-rc.19":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.19","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.9","nornj-react":"^5.0.0-rc.8"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.19","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Ty/Xyi6eGtiAKpYSnpnwK/p4l75pC+4lHLH4ZagBlZU43AAqDfza68WSyRGCYiK/C8BdN9RG6Ydcy04C5zG6ew==","shasum":"52c6253bae43efcacc06764f978af2ee33a8f219","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.19.tgz","fileCount":12,"unpackedSize":52400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc2q+YCRA9TVsSAnZWagAAS88QAJEmOUl59PHrRtd6vN7b\nlPlEMM6wjmKhcOdI51z5hUYEPkjcXqWFcBxuwk2mvIF5GPf0mlDeeyP+UNqh\nyxSLtMRVTuNwyPibU1Zxk1hYl2lUzMQ+2F8FdZQQazuACXsfyK5XTsPnKD+I\nY1gsutckKsMk1Oi9yZ+lybDD5LPzV1848aGNpgIYi9tm5ZB5nDoWSc9oNaSb\n1fXRFetVOKwupQlf9HKNEtc6hrAZ9vLxwgIkABtLecWXIiMO5tC0ddymxrUg\nefcHEeatAfKCpmyU7ctIOIrzGuKUH125d9hxPv2Z7gieGZbUqvm4xixp0rfX\nvdG4aG1BPMky9S4V01/+Q1wc8a+seZBU+61X6tumMOPAtDd+/rtzMGKU7tCe\nXPkloCzx3f2TPF5dZhaDAMMos8oupb+lpkf5NJXeHlkg0V5gp2hAVr0gpipI\nEUhjFli2edsSYRI3/ZUX01p8+Zkd5wOfMxIgo5GqZEjNVoKm6bLeR41pBqxC\nudlXFB3on9iCVyVh/oBmREK2JGbv1VUNl2iH3pQkKbnqAmF+txFZPIHAW0VK\n+grW9u+abrr2ssvTuIL3jQeBvh1ypVwOrbfGh1gp5WisQYch74sX7fT2zxQa\nqEWX/bZiTr0t3M6xzPcMoID7QsBPp0sP8ar+VA+HHgwm9P1DIciAw0Gce65Y\nnu5W\r\n=tXMt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+UMXGlv9vv3ox7E/yh+tYoeI7vALyXOlmV5OYGVOwjgIgDhq9zlgAYA6l509OvM2Y0R3GCSJdYHW1his/9yejXCM="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.19_1557835672206_0.792059280920304"},"_hasShrinkwrap":false},"5.0.0-rc.20":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.20","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.9","nornj-react":"^5.0.0-rc.9"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以同时使用`n-debounce`为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-defaultValue=\"inputValue\" n-debounce={200} />;\r\n  }\r\n}\r\n```\r\n\r\n使用方法如上，但有两个须要注意的地方：\r\n\r\n1. `n-debounce`必须在`n-mobxBind`的后面添加，注意顺序。\r\n2. `n-mobxBind`需要添加`defaultValue`参数。\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.20","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-RxquNqBJuq9zx4UXNTKjU6kT3+kWyO8f+/KTKkC2NQUhjyIT6QxiuxIFj0YXsyVEJZc+qHORG85r7Qe/6nmLLQ==","shasum":"9910b7895ac77bae8a58d5e54d55bfeb81c60b9f","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.20.tgz","fileCount":12,"unpackedSize":52400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc2rKBCRA9TVsSAnZWagAACW8P/RK+PAsOjLwLQXhL2Ox3\nxSOCu4qKzz38wP73GC3n+jBBao5wSxAr0qC6M0Crl8ZeGfEVNnCoBYwSVVsa\no7//MIx9dgD1LHACl4v7aNJXWu24knd5Cw8g/AMfOhy1+yVCB4A+iLIa9M0N\nfT+COLzH/cdx83ALvn2RCQjfSmu327GJu4AOgT7rSH+Rof8GnbZGDdZ6HJ6m\n66SpRMNGG+hU6YaH7oZxSQV8ieIfKaFc7KKxD8JK627nflDFglnFlAq4zQrb\nn9mQu3myNFIon1PhBozKVKInykIE2PQovydXEVNrWoSkhH+zEudJveyeLDP0\nB9FJZziH7tAO8J4EmbfHEh4FLqN2zZEKf4a/muP0cEhqdUD+oQ9BtYHkhWTW\nxvjVCr4jo7bBGwgQS6I1dq7wVRL6Fp6LyJLModfQuwadwzz3wqp07atVW3ml\nUbG/7NjLf7/sFsR+tQX0ZbwlpRR3TSUfEWsqLi4hZrBTVJ/GDwFRZpnQQ4CD\nCHHvxA/s0otBI6Bel4o30gzhhDAEARbAel1ZOYLUTFMGEuDzezKXXtMu/U+c\n3wbHhVwTdn6mHRzf/lbcCoajZgeB7ENQJHJDVGYXULf+a8EMR6JSD1+YO1Mq\nPStqBKT59wVT9if9dXWvG4bZjqQcPjMoFR+jleckYe+OPn+3yBqLNIIwq1/L\nJXs8\r\n=k35+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHs2uMMyc8EWoYTc1elGi5BF/dywnsoPu34AYIOCM4p1AiEAyuzPiPeNU3LS83mQC93BSJUEdvT/+EfOpWRF1CAZMNA="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.20_1557836417023_0.3649335288296762"},"_hasShrinkwrap":false},"5.0.0-rc.21":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.21","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.10","nornj-react":"^5.0.0-rc.10"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.21","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-o1hvgavzBMvkYNxwlOBJMpIh+JfSW15qzlpMw2EF+XguvGuLTOnJlL81RbbM24G/IutR2jbaenXKnIF94Q9OwA==","shasum":"fe26bfdc223ffd6da81b35862c52ab1a6d95506e","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.21.tgz","fileCount":12,"unpackedSize":52712,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc4mtfCRA9TVsSAnZWagAAVLkP+wRt24nyrjsFR1OpOdJ1\nF4nOOOaY3ndD6BLe4FB26b0zVpoLKbpTxtpfHqvUsy+tItjZ9bBwSJRR5YJr\nGMvUkJB0e62tD2eddJ/xsZ0VF5ZMijYMi3VR2RJ05DRdIzDtp+k2stGJsYxX\nLrcEUSnS6CmzvXA2+vEb0CTO5dCOar0lZc1ZFE/A5JJUWoQ0He4GeYqr8rDE\nw/zE5ekggek41cdvSqpdS5XhtbABYD7qoVX8Rn+C6Ew4QpWOPH97IJS/TL9D\nLSJq7j1Nvwbss2UZoIEpJQkS2vYZb7QOlNE0+ggI8m93Sd6BLXhcp1urW8po\nBeXoaO1bbP/cwk+Ju+uGf8RSAfVZMZb8XMKGZZXVW+rh5IoMi7DWg2h8tbEh\nY3eiJyMMgbP2Kl3QWt/EE2jVXEupLpn93m4APOoxwYxkxXM5INE0W6VJTZT5\nwKZRJA1qNwqx08jg572s/NyVIqHe7LqRW8LFvhMLFF7xDEP+VKv9dqSY/pJz\nhY74KQV6m33abtOHT5RFb4OjNOezaHnurqQXT0bhd5Jj4tjrss5i5SbkSjDu\nR7bSVfReURawGMRpQVAxc0dhIk9pQmvZ2icZxs8M/QLghMaFl3P2wIJxqRB0\nVDDZpurjs2aG9M4lXErJtWSx/T6fX9dTnSZb8RTq9a/RJ3ksCEYyXQILZYYW\nWfXX\r\n=QDaK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHji/m7WT9huWlFJeumidxckMo+MxKINM5bM88yclb/hAiEAmr/JhDy2VSkVGaOZrUofADzABuvA4uJhiMLd2mTTPh4="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.21_1558342494561_0.9169817936383386"},"_hasShrinkwrap":false},"5.0.0-rc.22":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.22","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.11","nornj-react":"^5.0.0-rc.10"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.3.0","react-dom":"^16.3.0","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\n  </a>\n  <a href=\"https://babeljs.io/\">\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\n  </a>\n  <div>\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\n  </div>\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\n</div>\n\n[![NPM Version][npm-image]][npm-url]\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\n[![NPM Downloads][downloads-image]][npm-url]\n\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\n\n```js\nconst Button = () => {\n  return (\n    <div>\n      <for i={0} to={10}>\n        <if condition={i < 5}>\n          <i>less than 5</i>\n          <else>\n            <i>greater than 5</i>\n          </else>\n        </if>\n      </for>\n    </div>\n  )\n}\n```\n\n以及类似Vue、Angular的指令：\n\n```js\nconst Button = (props) => {\n  return (\n    <div>\n      <input type=\"button\" n-show={props.showBtn} />\n    </div>\n  )\n}\n```\n\n还有过滤器：\n\n```js\nconst Button = (props) => {\n  return (\n    <div>\n      {n`${props.name} | capitalize`}\n    </div>\n  )\n}\n```\n\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\n\n```js\nimport nj from 'nornj';\nimport cn from 'classnames';\nnj.registerExtension('class', opts => cn(opts.value()));\n\nconst Button = (props) => {\n  return (\n    <div>\n      <input type=\"button\" n-class={{\n        className1: true,\n        className2: props.hasClassName2\n      }} />\n    </div>\n  )\n}\n```\n\n## 为什么创建这个插件？\n\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\n\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\n\n## 目录\n\n* [安装](安装)\n* [它是如何工作的](#它是如何工作的)\n* [标签](#标签)\n  * [If](#if)\n  * [Each (For)](#each)\n  * [Switch](#switch)\n  * [With](#with)\n  * [MobxObserver](#mobxObserver)\n  * [开发新的标签](#开发新的标签)\n* [指令](#指令)\n  * [n-show](#n-show)\n  * [n-style](#n-style)\n  * [n-debounce](#n-debounce)\n  * [n-mobxBind](#n-mobxBind)\n  * [n-mstBind](#n-mstBind)\n  * [开发新的指令](#开发新的指令)\n* [表达式](#表达式)\n  * [过滤器](#过滤器)\n    * [capitalize](#capitalize)\n    * [lowerFirst](#lowerFirst)\n    * [camelCase](#camelCase)\n    * [int](#int)\n    * [float](#float)\n    * [bool](#bool)\n    * [isObject](#isObject)\n    * [isNumber](#isNumber)\n    * [isString](#isString)\n    * [isArrayLike](#isArrayLike)\n    * [currency](#currency)\n    * [开发新的过滤器](#开发新的过滤器)\n  * [自定义运算符](#自定义运算符)\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\n    * [a .. b (范围运算符)](#范围运算符)\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\n    * [a <=> b (飞船运算符)](#飞船运算符)\n    * [a ** b (乘方)](#乘方)\n    * [a %% b (向下取整)](#向下取整)\n    * [开发新的运算符](#开发新的运算符)\n\n## 安装\n\n```sh\nnpm i babel-plugin-nornj-in-jsx\n```\n\n`.babelrc`配置：\n\n```js\n{\n  \"plugins\": [\n    \"nornj-in-jsx\"\n  ]\n}\n```\n\n## 标签\n\n### if\n\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <if condition={a.b == 1}>\n          <i>ifBlock</i>\n          <else>\n            <i>elseBlock</i>\n          </else>\n        </if>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        {nj`\n          <if ${a.b == 1}>\n            ${<i>ifBlock</i>}\n            <else>\n              ${<i>elseBlock</i>}\n            </else>\n          </if>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n更复杂的例子：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1, c: 'abc' };\n\n    return (\n      <div>\n        <if condition={`${a}.b.trim() == 1`}>\n          ddddd\n          <i>aaaaa</i>\n          <elseif condition={a.b == 2}>\n            <i>ffffff</i>\n            <div className=\"las2\">\n              <i>888888</i>\n            </div>\n          </elseif>\n          <elseif condition={`${a}.b == 2`}>\n            <i>gggggg</i>\n          </elseif>\n\n          <else>\n            ccccc\n            <if condition={!true}>\n              <i>bbbbb</i>\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\n                <i>ffffff</i>\n              </elseif>\n              <else>\n                <i>eeeee</i>\n              </else>\n            </if>\n          </else>\n\n        </if>\n      </div>\n    );\n  }\n}\n\n/* 输出：\n<div>\n  ccccc<i>ffffff</i>\n</div>\n*/\n```\n\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\n\n```js\nconst a = { b: 1, c: 'abc' };\n...\n\n<if condition={`${a}.b.trim() == ${1}`}>\n...\n</if>\n```\n\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\n\n```js\n<if condition={a.b.trim() == 1}>\n...\n</if>\n```\n\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\n\n### each\n\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\n          <i>{item}</i>\n          <i>{index}</i>\n        </each>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        {nj`\n          <each ${[1, 2, 3]}>\n            #${({ item: item, index: index }) => {\n              return [\n                <i key={0}>{item}</i>\n                <i key={1}>{index}</i>\n              ];\n            }}\n          </each>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\n\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\n          <i>{item}</i>\n          <i>{index}</i>\n        </each>\n      </div>\n    );\n  }\n}\n```\n\n### switch\n\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <switch value={a.b}>\n          <case value={1}>\n            <i>1</i>\n          </case>\n          <case value={2}>\n            <i>2</i>\n          </case>\n          <default>\n            <i>3</i>\n          </default>\n        </switch>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        {nj`\n          <switch {{${a.b}}}>\n            <case {{${1}}}>\n              ${<i>1</i>}\n            </case>\n            <case {{${2}}}>\n              ${<i>2</i>}\n            </case>\n            <default>\n              ${<i>3</i>}\n            </default>\n          </switch>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n如上，value参数的格式和上面if的condition是一样的。\n\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <switch value={`${a}.b`}>\n          <case value={`${' 1 '}.trim()`}>\n            <i>1</i>\n          </case>\n          <case value={`'02'.substr(1) | int`}>\n            <i>2</i>\n          </case>\n          <default>\n            <i>3</i>\n          </default>\n        </switch>\n      </div>\n    );\n  }\n}\n```\n\n## 指令\n\n### n-show\n\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    return <input n-show={this.props.show} />;\n  }\n}\n\nReactDOM.render(<TestComponent show={false} />);\n/*\n 渲染结果：<input style=\"display:none\" />\n*/\n```\n\n### n-style\n\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\n    return <input n-style=\"margin-left:10px;padding:0\" />;\n  }\n}\n```\n\n在`n-style`中也可以动态嵌入变量：\n\n```js\nconst cssProp = 'padding';\n\nclass TestComponent extends Component {\n  render() {\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\n  }\n}\n```\n\n### n-debounce\n\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\n\n```js\nclass TestComponent extends Component {\n  onChange = e => {\n    //每次输入后延迟一定毫秒才触发一次\n    console.log(e.target.value);\n  };\n\n  render() {\n    return (\n      <>\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\n        <input n-debounce={200} onChange={this.onChange} />\n      </>\n    );\n  }\n}\n```\n\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\n\n* 指定任意事件\n\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\n\n```js\nclass TestComponent extends Component {\n  onInput = e => {\n    console.log(e.target.value);\n  };\n\n  render() {\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\n  }\n}\n```\n\n### n-mobxBind\n\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\n\n* 基本使用方法\n\n```js\nimport { Component } from 'react';\nimport { observable } from 'mobx';\n\nclass TestComponent extends Component {\n  @observable inputValue = '';\n\n  render() {\n    return <input n-mobxBind=\"inputValue\" />;\n  }\n}\n```\n\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\n\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\n\n```js\nclass TestComponent extends Component {\n  @observable inputValue = '';\n\n  onChange = e => {\n    this.inputValue = e.target.value;\n  };\n\n  render() {\n    return <input value={this.inputValue} onChange={this.onChange} />;\n  }\n}\n```\n\n* `onChange`事件\n\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\n\n```js\nclass TestComponent extends Component {\n  @observable inputValue = '1';\n\n  onChange = e => {\n    console.log(e.target.value);\n  };\n\n  render() {\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\n  }\n}\n```\n\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\n\n* 增加防抖效果\n\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\n\n```js\nimport { Component } from 'react';\nimport { observable } from 'mobx';\n\nclass TestComponent extends Component {\n  @observable inputValue = '';\n\n  render() {\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\n  }\n}\n```\n\n* 使用`action`更新变量\n\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\n\n```js\nimport { observable, action, configure } from 'mobx';\n\n// don't allow state modifications outside actions\nconfigure({ enforceActions: true });\n\nclass TestComponent extends Component {\n  @observable inputValue = '1';\n\n  @action.bound\n  setInputValue(v) {\n    this.inputValue = v;\n  }\n\n  render() {\n    return <input n-mobxBind-action=\"inputValue\" />;\n  }\n}\n```\n\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\n\n### n-mstBind\n\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\n\nstore：\n\n```js\nimport { types } from \"mobx-state-tree\";\n\nconst TestStore = types.model(\"TestStore\",\n  {  \n    inputValue: '1'\n  })\n  .actions(self => ({\n    setInputValue(v) {\n      self.inputValue = v;\n    }\n  }));\n```\n\ncomponent：\n\n```js\n@inject('rootStore')\n@observer\nclass TestComponent extends Component {\n  render() {\n    return <input n-mstBind=\"rootStore.testStore\" />;\n  }\n}\n```\n\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\n\n## 表达式\n\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\n\n```js\nimport nj, { expression as n } from 'nornj';\n\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <if condition={a.b == 1}>\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\n        </if>\n      </div>\n    );\n  }\n}\n```\n\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\n\n## License\n\nMIT\n\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.22","_npmVersion":"6.4.1","_nodeVersion":"10.15.1","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-i/eoQD+PYPGTOGZNlcLxucMpDrhoFHJve22/KyfiVNSnah7EipFBx9ZztDb1RVBx7sqMssYFiRlufv7q568bWg==","shasum":"78d117720911499332f5ccb575c054303cf35042","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.22.tgz","fileCount":12,"unpackedSize":51143,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc5OwxCRA9TVsSAnZWagAAaOUP/1LOvgIQ3MfiYPtivG7r\nekg60GgMR/5bcauIdzNI6zZzFKrqz3qI/jcKlAq3SnbdiYf0grUjXzpZz7S0\n8vZyZ/uKBtRKgVimw3lBFyJTxrhlyduM0kghV/pDbyKBKUl+Lmkx9M8UBtmX\nA4qXMr/cFZIUnLdW6ByhagUzU4JQlJ89ZR1aF/s+dMucWoQHWV29Y4knmlO+\npyCRhhAmf3+B/RnkLy6E2vx4gpdulrm8fjnk2RVVOlPbqJt6geW0T/29q2pu\nPo4WeejBZBIyq61PA6BCb0+CAsb+ea83bmEL/8+Qj0myUIxLNEkaO/V9dFE6\nwuXA/DMQX2b0WPsivb7uLhYlrbfR568gDTXJEpGBXfge1HhW8q8/Tx3elBRQ\nwLfMd971kCSjLrqFmjuAXA8u232hgISmkdTkyY3l4GoEAt0jkij4cU5hOio1\n5dvcr3pMMtrDEesfg2SIB3EE7VPwmJOcmfDoBx0KV45aEZU9jqenWasE1ZUx\nCs4ANzcS9oNN8iROp5jczt7Dk5GtPNXC6IqmtwBPyeagWa+uMOV5ekyJHPTU\n6mqq5brLG+XrYcTYKCWztpv/XuifVAQTx1oqTQATiC+3RM+CCYokPM9AVjGz\nCb5jXj0Y7NZyZAUDhOPbvBLn4pELVG+VFiudEPyh6mFgcufnI0uJ6zKdvEvG\nIZ/P\r\n=j8Op\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZMZWB43p1FOsgBaBnDwotB2tZNkMAhtYS4SZvBxWwAQIgBH/SBYGFypudRl7a5GsWQe9j7w2b8A3eUS6MR0DvmOM="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.22_1558506544880_0.7973910572350598"},"_hasShrinkwrap":false},"5.0.0-rc.23":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.23","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.12","nornj-react":"^5.0.0-rc.10"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\n  </a>\n  <a href=\"https://babeljs.io/\">\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\n  </a>\n  <div>\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\n  </div>\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\n</div>\n\n[![NPM Version][npm-image]][npm-url]\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\n[![NPM Downloads][downloads-image]][npm-url]\n\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\n\n```js\nconst Button = () => {\n  return (\n    <div>\n      <for i={0} to={10}>\n        <if condition={i < 5}>\n          <i>less than 5</i>\n          <else>\n            <i>greater than 5</i>\n          </else>\n        </if>\n      </for>\n    </div>\n  )\n}\n```\n\n以及类似Vue、Angular的指令：\n\n```js\nconst Button = (props) => {\n  return (\n    <div>\n      <input type=\"button\" n-show={props.showBtn} />\n    </div>\n  )\n}\n```\n\n还有过滤器：\n\n```js\nconst Button = (props) => {\n  return (\n    <div>\n      {n`${props.name} | capitalize`}\n    </div>\n  )\n}\n```\n\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\n\n```js\nimport nj from 'nornj';\nimport cn from 'classnames';\nnj.registerExtension('class', opts => cn(opts.value()));\n\nconst Button = (props) => {\n  return (\n    <div>\n      <input type=\"button\" n-class={{\n        className1: true,\n        className2: props.hasClassName2\n      }} />\n    </div>\n  )\n}\n```\n\n## 为什么创建这个插件？\n\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\n\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\n\n## 目录\n\n* [安装](安装)\n* [它是如何工作的](#它是如何工作的)\n* [标签](#标签)\n  * [If](#if)\n  * [Each (For)](#each)\n  * [Switch](#switch)\n  * [With](#with)\n  * [MobxObserver](#mobxObserver)\n  * [开发新的标签](#开发新的标签)\n* [指令](#指令)\n  * [n-show](#n-show)\n  * [n-style](#n-style)\n  * [n-debounce](#n-debounce)\n  * [n-mobxBind](#n-mobxBind)\n  * [n-mstBind](#n-mstBind)\n  * [开发新的指令](#开发新的指令)\n* [表达式](#表达式)\n  * [过滤器](#过滤器)\n    * [capitalize](#capitalize)\n    * [lowerFirst](#lowerFirst)\n    * [camelCase](#camelCase)\n    * [int](#int)\n    * [float](#float)\n    * [bool](#bool)\n    * [isObject](#isObject)\n    * [isNumber](#isNumber)\n    * [isString](#isString)\n    * [isArrayLike](#isArrayLike)\n    * [currency](#currency)\n    * [开发新的过滤器](#开发新的过滤器)\n  * [自定义运算符](#自定义运算符)\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\n    * [a .. b (范围运算符)](#范围运算符)\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\n    * [a <=> b (飞船运算符)](#飞船运算符)\n    * [a ** b (乘方)](#乘方)\n    * [a %% b (向下取整)](#向下取整)\n    * [开发新的运算符](#开发新的运算符)\n\n## 安装\n\n```sh\nnpm i babel-plugin-nornj-in-jsx\n```\n\n`.babelrc`配置：\n\n```js\n{\n  \"plugins\": [\n    \"nornj-in-jsx\"\n  ]\n}\n```\n\n## 标签\n\n### if\n\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <if condition={a.b == 1}>\n          <i>ifBlock</i>\n          <else>\n            <i>elseBlock</i>\n          </else>\n        </if>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        {nj`\n          <if ${a.b == 1}>\n            ${<i>ifBlock</i>}\n            <else>\n              ${<i>elseBlock</i>}\n            </else>\n          </if>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n更复杂的例子：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1, c: 'abc' };\n\n    return (\n      <div>\n        <if condition={`${a}.b.trim() == 1`}>\n          ddddd\n          <i>aaaaa</i>\n          <elseif condition={a.b == 2}>\n            <i>ffffff</i>\n            <div className=\"las2\">\n              <i>888888</i>\n            </div>\n          </elseif>\n          <elseif condition={`${a}.b == 2`}>\n            <i>gggggg</i>\n          </elseif>\n\n          <else>\n            ccccc\n            <if condition={!true}>\n              <i>bbbbb</i>\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\n                <i>ffffff</i>\n              </elseif>\n              <else>\n                <i>eeeee</i>\n              </else>\n            </if>\n          </else>\n\n        </if>\n      </div>\n    );\n  }\n}\n\n/* 输出：\n<div>\n  ccccc<i>ffffff</i>\n</div>\n*/\n```\n\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\n\n```js\nconst a = { b: 1, c: 'abc' };\n...\n\n<if condition={`${a}.b.trim() == ${1}`}>\n...\n</if>\n```\n\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\n\n```js\n<if condition={a.b.trim() == 1}>\n...\n</if>\n```\n\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\n\n### each\n\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\n          <i>{item}</i>\n          <i>{index}</i>\n        </each>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        {nj`\n          <each ${[1, 2, 3]}>\n            #${({ item: item, index: index }) => {\n              return [\n                <i key={0}>{item}</i>\n                <i key={1}>{index}</i>\n              ];\n            }}\n          </each>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\n\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    return (\n      <div>\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\n          <i>{item}</i>\n          <i>{index}</i>\n        </each>\n      </div>\n    );\n  }\n}\n```\n\n### switch\n\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\n\n```js\n//转换前：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <switch value={a.b}>\n          <case value={1}>\n            <i>1</i>\n          </case>\n          <case value={2}>\n            <i>2</i>\n          </case>\n          <default>\n            <i>3</i>\n          </default>\n        </switch>\n      </div>\n    );\n  }\n}\n\n//转换后：\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        {nj`\n          <switch {{${a.b}}}>\n            <case {{${1}}}>\n              ${<i>1</i>}\n            </case>\n            <case {{${2}}}>\n              ${<i>2</i>}\n            </case>\n            <default>\n              ${<i>3</i>}\n            </default>\n          </switch>\n        `()}\n      </div>\n    );\n  }\n}\n```\n\n如上，value参数的格式和上面if的condition是一样的。\n\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <switch value={`${a}.b`}>\n          <case value={`${' 1 '}.trim()`}>\n            <i>1</i>\n          </case>\n          <case value={`'02'.substr(1) | int`}>\n            <i>2</i>\n          </case>\n          <default>\n            <i>3</i>\n          </default>\n        </switch>\n      </div>\n    );\n  }\n}\n```\n\n## 指令\n\n### n-show\n\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    return <input n-show={this.props.show} />;\n  }\n}\n\nReactDOM.render(<TestComponent show={false} />);\n/*\n 渲染结果：<input style=\"display:none\" />\n*/\n```\n\n### n-style\n\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\n\n```js\nclass TestComponent extends Component {\n  render() {\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\n    return <input n-style=\"margin-left:10px;padding:0\" />;\n  }\n}\n```\n\n在`n-style`中也可以动态嵌入变量：\n\n```js\nconst cssProp = 'padding';\n\nclass TestComponent extends Component {\n  render() {\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\n  }\n}\n```\n\n### n-debounce\n\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\n\n```js\nclass TestComponent extends Component {\n  onChange = e => {\n    //每次输入后延迟一定毫秒才触发一次\n    console.log(e.target.value);\n  };\n\n  render() {\n    return (\n      <>\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\n        <input n-debounce={200} onChange={this.onChange} />\n      </>\n    );\n  }\n}\n```\n\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\n\n* 指定任意事件\n\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\n\n```js\nclass TestComponent extends Component {\n  onInput = e => {\n    console.log(e.target.value);\n  };\n\n  render() {\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\n  }\n}\n```\n\n### n-mobxBind\n\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\n\n* 基本使用方法\n\n```js\nimport { Component } from 'react';\nimport { observable } from 'mobx';\n\nclass TestComponent extends Component {\n  @observable inputValue = '';\n\n  render() {\n    return <input n-mobxBind=\"inputValue\" />;\n  }\n}\n```\n\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\n\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\n\n```js\nclass TestComponent extends Component {\n  @observable inputValue = '';\n\n  onChange = e => {\n    this.inputValue = e.target.value;\n  };\n\n  render() {\n    return <input value={this.inputValue} onChange={this.onChange} />;\n  }\n}\n```\n\n* `onChange`事件\n\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\n\n```js\nclass TestComponent extends Component {\n  @observable inputValue = '1';\n\n  onChange = e => {\n    console.log(e.target.value);\n  };\n\n  render() {\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\n  }\n}\n```\n\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\n\n* 增加防抖效果\n\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\n\n```js\nimport { Component } from 'react';\nimport { observable } from 'mobx';\n\nclass TestComponent extends Component {\n  @observable inputValue = '';\n\n  render() {\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\n  }\n}\n```\n\n* 使用`action`更新变量\n\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\n\n```js\nimport { observable, action, configure } from 'mobx';\n\n// don't allow state modifications outside actions\nconfigure({ enforceActions: true });\n\nclass TestComponent extends Component {\n  @observable inputValue = '1';\n\n  @action.bound\n  setInputValue(v) {\n    this.inputValue = v;\n  }\n\n  render() {\n    return <input n-mobxBind-action=\"inputValue\" />;\n  }\n}\n```\n\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\n\n### n-mstBind\n\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\n\nstore：\n\n```js\nimport { types } from \"mobx-state-tree\";\n\nconst TestStore = types.model(\"TestStore\",\n  {  \n    inputValue: '1'\n  })\n  .actions(self => ({\n    setInputValue(v) {\n      self.inputValue = v;\n    }\n  }));\n```\n\ncomponent：\n\n```js\n@inject('rootStore')\n@observer\nclass TestComponent extends Component {\n  render() {\n    return <input n-mstBind=\"rootStore.testStore\" />;\n  }\n}\n```\n\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\n\n## 表达式\n\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\n\n```js\nimport nj, { expression as n } from 'nornj';\n\nclass TestComponent extends Component {\n  render() {\n    const a = { b: 1 };\n\n    return (\n      <div>\n        <if condition={a.b == 1}>\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\n        </if>\n      </div>\n    );\n  }\n}\n```\n\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\n\n## License\n\nMIT\n\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.23","_npmVersion":"6.4.1","_nodeVersion":"10.15.1","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-wtmNNaSD5d/ra5++Wp1lquAXF2xJcO7Ys1g4oYbYkpllJlerKBLVk0hE7uWR75LXa+DYvtkl6Y8nmYc188+7hg==","shasum":"c9d3e9d65c9b9ff0d872502b95ffa35d06e5b2da","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.23.tgz","fileCount":12,"unpackedSize":51158,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc5k4nCRA9TVsSAnZWagAAIyoP/RUJ5tdoxVtywJgAKkDA\ntS31xjBn7xyd3L4yJpyXKC1T81L/o0sYud7sViM3dkBhrKIQdBe/+A4dY1EX\n0Xq2Svuc0B5C4R+aYAVlK2Q7Y14qEfCqHXLqDyY4ccZjYGLsBlL5LtAdtlgM\nvVBbKU1Ev7BrKx9Ha67iDpVL7qKDg/dWDCT923/0nGFXDVlDOAVcK8DJdZx/\n+Da1n+veACrpH7YzOa6x02WYt5l7iHwft2ulRc7mffyBu2PDihT4Ha+khHra\nSS356wzP+2VbdF0sSonlB5gr/okyDNq9Ji6M0b9WjuE+2oNkTgSDAKixPEiC\nahBg7oWmFq85yWCGpTryS6AagObOSrcJeMdnauT5YhLWQN4PVmj746svI23W\nPY9Mu35EHeDq7uJ91z0s8jxO4l7YT7kaTD/Y9PMir+6bHmoO4CV6v+EdWrDW\nDqOS1F7Q275rBGz0PldwpRkOR54fwbEtMHOoM7d8bCPQVEEABPsV6//pNNvt\nm/Eo5mu8DnKiC5tbrQLfEc0FddT4WRtHXSFgDd0SUlYgH/nZTXbfswFMgltL\nQUQxmuO0tYQ8RZ+wpO8R4mFuROxKeNg7g7rFzA9VX3fq040dZnZsZ7n4c+sJ\nQMDYBkc+J+tFGrE7I5Ol2+fvk66ZUu7IAczFa7R6xr6Mejxy64cboSbPr5s8\nqWV9\r\n=EgXj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFcw+PtaWgflKZB9GxdrczuSsKOW3Ps50VdpQtP2wzFFAiEAvZag/191EIRRH0vOHiFyguKJOZTeMyNbXSxbw9H8SvQ="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.23_1558597158767_0.018121255897482813"},"_hasShrinkwrap":false},"5.0.0-rc.24":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.24","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.12","nornj-react":"^5.0.0-rc.13"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.24","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-So6H9j9WC09WCoK9GOSOuJAzEBR1NUc0c5VOeoQupokg4bgnz2Rp9Acz/Zpq9EXky5lvbI2ihKGP59BXMl2jsQ==","shasum":"ee0662cb88148c3fc121cdb065ae119e75e1ef69","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.24.tgz","fileCount":12,"unpackedSize":52677,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9710CRA9TVsSAnZWagAAwrIP/RNRSFY0QzDcExVG9H7X\ncbadhBsPXx9mPtup7949SaryoHwdCuobjwFwSCmyJvl+FzY2qLAtSLpfpX+T\nUAv2cDAoFjuNxTOsHcbW7tYmr8y2wM/2+VbAllhbowds6fFdS2S05Hh6ssBc\ndUUmp0NOFNExB2WFVGGD4uRnthy9l13IrDdyM2qinKlm2EABTH67q6OZ4A8R\nFC31T2Mp3pnCgAkU+m2+PvqD80ZYbc04rKDioZfjgzwqCcxtF3szpU0S8skC\nBFAwI+jI1gvqQ+NKaaeS1yV+Nzl9qjoEBtOad4inXmf0qmF2qg4nvm0ihTaQ\neFVqBnEBuMarp4w76sUJrZrqA0j8QjxZcoOXPzszz9VYG/bBLoF9XC0ZrdhW\n8CzjIHUtEeWA1OkO8T0Kuvn4PHTiNthABFk0iXg47O4JrDnG0PDBrDETJ3Jw\nxnmxok7Qy3pmsOjZ8x+kC9V3xS5L2c+LoV9rLuZhC8J9gIkcThkSGKVTNfgd\nTakGNrqCmEW8dC33WnHe6FgKSrjDZmXQUUptSqQXkVAEy5tntIoVq7aF6xBy\nDhS7ggL2H+BMHtaTtTxNVZ442ee2++FTzBiSIh9tU/ciJYFJhIKl35Vk2Fiu\nNzxxTL77x9IJXxTJl+ZuMaFkj8ccP59jrII6KUiswIth18b/U5DSQbBsqPhv\nHpt/\r\n=y5BF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFQjMdAVOL0Itmn7DrzZpG12e9shTifDh46JuXO+z0heAiAfvzvLEr+9mIBtPpkaaQ2YtKZ+ZJbFHb4nLgCiEgilFA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.24_1559739763209_0.2072514627269384"},"_hasShrinkwrap":false},"5.0.0-rc.25":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.25","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.14","nornj-react":"^5.0.0-rc.13"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.25","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-cPmK6t2M3lECwCyeTKepbPYhq2m1ndxhrUpZEZljlQs0XXOtJo69ZLmqDD7YVGY12W7t9NBMNsLdegd8dkCRZQ==","shasum":"ccdeb3efc7b54b7b21df7cdfa0ae169a1178d773","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.25.tgz","fileCount":12,"unpackedSize":53276,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdA0dCCRA9TVsSAnZWagAAJsAP/3EnBOHxdVcjw20LVfo+\n7x2UPd3q8z07Rlqs4j7Z3Ss3JOgcfk4/0N7H3rfWScYbbWTtpPk193dTNQ/6\nucUxukSbq2aLxabRAXwLWtDz8t3xeKCQbw3nwWv8BVMO5L9DUNc7MO7u5SIC\nH6sHH63d2QcY5hRTr8qw6F7I864z7NwBtIau0gjSykQR8N5jnW2EOnkDXZ61\nr0UkWG/8q8D3VGEtfeK8evZJSVI6ZZPIQvF6Wdoi+Zo2HizI/0Bt8zLyBKcN\nLnV1Edwp51JjTg6HzPiDVGxLbDt3onJFWkd+I4cxl/YrDn5ENltNNQdOBOS7\ntT9Sn/V2SQ/j+PTrCu74UwFm6y3j7i2LGNeH7TwPuUh4R2f4ZKf3IHksmNZw\nkF8PyOjejG++8t0KBcO86HsGbnI1S2kU3RUErUEw+FzBxGJSGeifj5HaArE6\nXzRYRt6c36sqRy4r/MvjzuHoy+p+CYf4Q9OJHIj9Cx+t7eVDgfIM44WtkB7a\ntTNepo5iyrGIOFfZl79Q9hacfusCcLFigAjDThrWxCVWNpnT8ANt1Gbg9kOR\nCbgDZYIIz2dEhN8U4rCiOsFRN8WzncK3tDdrckBY1hP8lf/CwHOD1fAKd8LM\nWN1XqUGylx5L7ErpCkqERc7q81meLUtlZu7kNxa3e0qtriXxWDVehEoEOdaA\nx2ZW\r\n=LyQE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbpsOyfU+JYtVcDd7PhSN+fHOXrmlXO1eHgWKCn4fJWQIgcP6QHTuFnY6cUsmTcCEd/K6TBwKYmxbHJG6lOVBvrLs="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.25_1560495937553_0.7306617793387908"},"_hasShrinkwrap":false},"5.0.0-rc.26":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.26","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.16","nornj-react":"^5.0.0-rc.13"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.26","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-lwNC4rmfUyl5KTXsPnsD4/tPXuu63ReajKYLbDiaCccV+Nh5wR1DM3AWpeWKGeXPt5tHTLIfEKLJ0KmrNQMMxw==","shasum":"c916be26dce6bc6f0c2175cf481a74a6c9a141ae","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.26.tgz","fileCount":12,"unpackedSize":53210,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdD4cKCRA9TVsSAnZWagAARKgP/3yon+Vd0CwdvkCvWHk9\n4eedmAA+D4MvJlkbH96TKTzwL5FkHehYDOP1R6jfRhkRuSeBZUPVDHJ0Uj5Z\nI1b32HAZGMAxHjBlD/uhlJetCmYHfw0jNn2wcnbTVYMr0q60owCLWdiI5xbd\nCQva/fSSpgcUaea90zK8xg7ueP19mlLNptLlHK425yXfVexlYoosVpMUDIKP\n6Af8KauHs6jSVD63YBW8IejuaXM1yAI4bnTshhfe+SIMewAFC0svOzXBkNpj\nm9m4btxrqBGLOuvX2fQ2ndgfNyHCLXpl1gxit84iT62jMJVIkuX+IZWIJTmj\nsJo/w81zMj8VIW+N2H881ocZcRpYefgm+JQYl0dBE6MASvXeG0CW2JqqxFt4\n8lPGswzHbj/1BND06n/pFMf/tENFIAxeUSabti2ltTzgs0SKtQe0o8e0Xaw6\nTUEYIZFa+02k+7+UcXKLJhJk7TLbrfdNcBHcYpp2l3uk6gspOWR2GeJaSlrb\nfmzBy6TfswnNaVw/vGUWHQfrMZC8LvNusSx0wowpW1qZ4mH+PltsCosbin6p\nUQQl9AqqnD0SZnGUNR1rAGk+RMfbHDAA44Nn6QAZu+AgvXyrLwPYQKyVOT9c\nuhFS5ntwHzPA+/729OSxiNqYWwLYuq6wqkKulzBdXi2WJ3K2YkaMkzbVk8tY\nykEI\r\n=7R4n\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBOaRUfXS63oxhMfj6HELk5FCjFqOzrvjlXP4TeKBPVPAiEAuyXnWRi1jh7hNtBBLYpBkTrSwcWPur/HYq+tlQwC54U="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.26_1561298697887_0.8873550773610326"},"_hasShrinkwrap":false},"5.0.0-rc.27":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.27","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.17","nornj-react":"^5.0.0-rc.13"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.27","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-BB7veReK9zw3PNiKB+Fyn9l99ZWzRlzpqEDhKPHCRZlFcVySODx3Oy8dB/N0TOUJx3BdE7xnel6Kxt3k2wsNkw==","shasum":"f6ac163c59174b7d0914a87b3694066cf44dacbf","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.27.tgz","fileCount":12,"unpackedSize":54360,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHH2uCRA9TVsSAnZWagAAsVQP/RkLBzID2SwwpJPNcVKE\n/P7Q5svrSTkqZx3s+DTRQXG/mpaUIPiM3DK7+WzxHUCUM6ouM+mQMRvUx5mY\nnWmEYcFQFoq1yqQx2zPwDfpfM7mP0GpVsLgoIg/PKYOLHICKlFlxEpns8ug+\nzhxvtIpX7DPJe5mjagicvgQ5VmKml2tZo/f/yNd01xtAYoyo/5z5THeOz6wJ\nayl85nuDWlXNi8WDJhsb5CiBI3eHukLWlBC0hKrq8EkTNc386YzWLI6YyLSm\nvouqctq/EDpIc1zTTy0ln/C/WD9qbT3RBKwvXcpjj75Abq0yV1B2wt9O0Cn3\nAKv29LnG3vYFxSIwgAU8Lju2i4iDEE81rWNVmN/Sk5Wvs9up6CVQxCFALouQ\njESMU/D8dLxG5MEUP9+5cTHBj4UroMTw4ZNzFi0inJtcCJYHCCaivOLGkr7z\nqcmuPU/bIV3L1mSo8fMwzMwYWuw79S7IQZ7yzuaBOLfFryvBukoKBftuZiLW\nd3ZG+LdID7AIr7BlrNguEdY1tP8S5AnpXfL/9n57ZKVJ3qpTbmYRANGNqRAd\nczNfQ0vbfJeRJL/oc5idVMTCl/i9NbQIJTl/ltTdFcm9nCbhst1k2qLjxcSn\npqAM0776xS25/wfz/vXe2HZHp7vyyEjJBwvKVDZ+xaLb8pl7DRKONrE5/DeX\nvQJJ\r\n=T7SC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGqcecVy9yEE9WmkhpIAXGFgxLZWS8xn6RsX/vTTpfTdAiBS6MN/koKJIE0Sn57TVV0Kj79BK5rOQEtCagErTRQHsQ=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.27_1562148269858_0.5535850028959535"},"_hasShrinkwrap":false},"5.0.0-rc.28":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.28","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.19","nornj-react":"^5.0.0-rc.14"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | capitalize`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.28","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-nXRolI/zn4ZG0w1gO14y55YbW629NaUlO7PhT8oUy82wKs5QXm6fis4cB6BhhbHv2T/+3Sfjugx6G6zyfsmZfA==","shasum":"d759987a324085aa4f9422f19db35c018890cd90","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.28.tgz","fileCount":12,"unpackedSize":54896,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOpBrCRA9TVsSAnZWagAANVMQAITAfynvFr0iChOiscc8\n+II7k0PIGNUu66gxfaEwczI5eSuPJUqXKX/8trs2XkHWMHAqoqla5wopcZ7f\nqE8DuUHMzPmNYEd5S1m1sktz1kcXtc/J3Az3Njecv9nSA/ss1KsMPO9v94bi\nC8FKw16xrByK1ZuZo5uR8AmgszjaRismgqZyKA/BYdhneJXo+NR7mNUVFn2U\nV1gbHVYcM61q5mTc+q7W+ZtEfruERE/FxAszrCippw4eKUpmBSlv4+doyzLO\nVlQRWaEO6siTP01xh+2YTj+DACUZWDzwCT3tmBHvU4H7iJnO2thTB4qBlvTK\n42xJjOh6lBplkNy9pG9KHgJjOCqVdtthrssbvN77lu7B5bhiESPyyB9aVQX2\nz2zsMVs5mH70WsGKQk4pQwMJxegi3dXDf1p0LZKPmjo/nPxhvzbyvYJfJ9QS\n4yhzjyc4XJ/MPxnqXY8srTjXg0H6CCe54sy8z3mF1q+Nj12dZZR9EIguEK0s\nvT1XhvLqYzISsjeKzZZjTpSR32M3UJBKdlqWbBdgKgEhWTy4wzMWByCLTbr4\njK+3gxu1/BY56UGNzt3Gl1TWeLGSMs8JE4c7wjGgGS4cx2aDIrN7Jg+78QF1\nK4l1nueBs/cqTBXR3iCxcpvA074wnmQ3MqBlOMVI8mo8T4/cMOuLjCScvdrU\numCj\r\n=CvfB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwcRITfdz/kIqOuOfVHUzbrvrwYu+Qdd5xCsIlH2opKAIgBf3gl138i0MyHwoU5g/udWsdXz4PQ3LldKzqnKiC3Pg="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.28_1564119147025_0.2728844650729514"},"_hasShrinkwrap":false},"5.0.0-rc.29":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.29","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.20","nornj-react":"^5.0.0-rc.14"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.29","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-pSGae0gEcVjPtveT4LS7SS+EdqRIclm/Y+4kz2I0XhnKzU5hRKulHTpkkC70wo1hIsXP031wkrSGhqH8UkND+A==","shasum":"253cd7dea8290c103a838ba93725f033a9ee1165","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.29.tgz","fileCount":12,"unpackedSize":54896,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdW+WKCRA9TVsSAnZWagAAeLAP/iqKq/R5ykIt1dCnqhpq\nR/QcFRBt78552SHzePTMOPwSsaPmweJxJ2m2OoC4G/r8oMcbYyMeNdEH/f22\nhxpjJV8XeZ/OWqIaPeryCdYELR/g7yvEdrta7zfJ0917SWgybadH6cGQS7PM\nWwrQ9ECbgbs9Bsu50pDySygVqs4SHkd7lYSAOTyTpjDVHBrBzvBa7bR/ZJDb\n+UPlVLz+5yK1OfqdRFtFP1wjZFj08pKraxZgpmn4YFbRSS0RYLVQKNdr3H0G\nuUJzYKzHQL9jK8kX95TVJdZjFoLNXxVgCkxD3z396nEy+wskn5PfDKOvyIg9\nalMPxi8KWpiMpInZ4CSUqqebL6vaah9is6hfyyWEJu2tC5YKbnWTsjeF4VSt\nkBvgMClTvptj3Zqa0dnth6IzEodIPb7vdljcwCtbeW7fZGOSY0ERB7G/DgPC\nLWwge2WhUn29ZRnrfvbMbbvkJYo1rnAJyS6KRKGkEF/aU4/bdhwKwbn9cjLc\nSBgLEHUh7lHZ0ACzD8jMKf5XDG9uJnL0D7A2D3GWFLo6j0HEAIHi8ijKLZnj\nz6KX6oeCTyT8ohx9+4BAqldci69N9ETHIs+dQO9oHqPgwVhBf6FbeeMi+wWx\n59i5Ov22KqqlEvDLaemz1B8tBw4gI6qYSB+O9QltkoIR/7FdQLbHUdg6lRd6\npbbQ\r\n=vc1Y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCviOjMHkL5rvbb5ZZR+QiMkxgb7leaQzXC3cIUC3y5AwIgQWH4D7WBQS3khYtiElDu/qRccgI233vECZdtKfINiNE="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.29_1566303625625_0.7430810288870029"},"_hasShrinkwrap":false},"5.0.0-rc.30":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.30","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.20","nornj-react":"^5.0.0-rc.15"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.30","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-r720QJYEokZqSaflISAWQo7CeQBBykp3IVnxHRFrROEGrX23+GQfJDU55g07Z1olDKOdnXfJS+G5XzTgVD3EuQ==","shasum":"307b251605e7167fea3fca1acda756811fa648c2","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.30.tgz","fileCount":12,"unpackedSize":54896,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdXQZMCRA9TVsSAnZWagAALZEP/RCN1nk9ARwdga1y1iPh\nY0vaExQ/+EG8oB3RBywT4qekbJU2eAK8cbS0W3683PTZWqD0GuChUZUTbMdB\nsfBFsd5chHshbD1fAPA+vbJKzM1HJkHx1tauXwjOzhAPPKbidDfjLwhruRxa\nCngjv+QuOivRetmdG9AfC10mMfJuomFppxzPNypDK98WnE0wNw/G2AwRP8WO\nYBGZeniRyFD4XQH0GIezbugWmBD5PEc/FQzo3R6YAef0VD6YevwFF7A8nS4h\nVMzLVaFjTXarUt80H/d8L9YHUNbzK+WcdFGm2up3ox8jR3NXrQR9R8JmdCNa\n6l+V7o0XgW/tCOSrBArO43TI/dwzJkPZwJpEpWTno4VnDjBIyw4pASWXGs6k\nsx5HU8X5rNjI0tHifKdcJ35hraN4u860fuf8vaXWINFqXNmbNk8HyVpcTT2D\nlW5woj6+KQ/Goyw13IPlr2gA8QswLFwiBzBcBejXIWVtDmutvMMmf57HKjR3\nerZXoXj461Lxtati4PtjUX5YwGikX+1eEI51JZDDagZacNzBKFNYYVcEuF3U\n2yqAPjPskRi8g5GygoMdXaxwg+gKKQIkosj+9917zx87UeuuaDNAbDpOLw/a\nBtHzUXFEZzvlhQCpJogzEdHN6lenwbzRPZ4uCj2UUn0fx9w26R1QMDSxpVR/\n3F+5\r\n=e3Dq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDFaMjszluSmRxmWo//L06zjnVjODgStjXZFWL0JaLN2gIgBEhdzztdUQEfraPK7CjEsU1OkONmFZV5fXeZl472uhc="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.30_1566377547605_0.3576916156090284"},"_hasShrinkwrap":false},"5.0.0-rc.31":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.31","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.21","nornj-react":"^5.0.0-rc.15"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.31","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Y/zVPh9xwFGKJAEFEbr/Xmvk7oohwccrdoa0ehQ3blKQJ4JGXX0DdvV/BGGjXZgeACsZ1qoy0IkTe69aQkpUdQ==","shasum":"494d0e44c676dd5cfd0fca9b5622d25744214491","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.31.tgz","fileCount":12,"unpackedSize":55656,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdXn0ECRA9TVsSAnZWagAAYTEP/0f79VBTfma5UeTQz+fd\n/oT7S1XHfVp+wXMUUVufkKLynjKBi9Kd2dfboV2RZh4m1n6OwTXxjTISRNE4\n8UNRUUYVAr3cKvKm74wMjBmVLjxzWsBcayFXth7AUr4M4X5hJWbemucQC6v+\nC7ZEPX2WzSAuTmImGd3dVgavZm4IQo8JATGBxaDlWmHpOlWK8dG4+CXDqP6x\nOReSF7kDjaKF76aTY475WOCoeQWWGDu1eaOcvs1GMTA4YhNk8ASYAb7c14mO\n+cKiUOu9z/ZScxiUMClnq1Ds/ffGG2HBjgmuQ4UPtu6AcAhYvS45G3nmQudj\n1qYnNRcxSD/dDPWG5azVWO0/B4a8Sn+9YSuzQRFSOEOb1AbmDx8m1xq+uRN7\nkYixHbB30Uo+imUA/UHpgr6fVRhqFQbhfGSb7eMFwpAggJLN6jZ7kZnYLAT+\nPEJ+XulWWC1ptaoOsjXKmI6iw4CONSQaqi0If+/95l0yPL22iEGhMRxriMBt\nzn4oSkX7XrWUK++Q9gp1YBipVahh450zGvbDuydD575ua3RL6I9f4oLR80ko\nTNl2fprpAzUBpqVhWURld+LNtQSXcMnITTNjGg3NQM4a9EHEIkhpBU1nDtoK\n+JS9LrH48VNgIibt0Wc8+bixO9MYTiLHDSb7arcP2tK47iJlaDOq1WCPpgEQ\n6ONc\r\n=257H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFzrwdkZqCqMcngum0mi2g/naiihzJI8jyJvpkeMDhH6AiEApvOipIldVQG0hyjsyNu75asSuV0ayspvKpVEV4MpnBs="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.31_1566473476110_0.9651414543409784"},"_hasShrinkwrap":false},"5.0.0-rc.32":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.32","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.22","nornj-react":"^5.0.0-rc.15"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.32","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Y+d78QMNR7VC4GUL4ysgDB6bzYQVOHKpDVYBRqKS7ZooirLCZ9YIF1xTeTtUCAom4SrYlJhLaMF5avSfTxSAng==","shasum":"781a5187c10ccffd13bc47103ecc6aeec90c19c1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.32.tgz","fileCount":12,"unpackedSize":55656,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdXoN0CRA9TVsSAnZWagAAfH0P/3PdFHKU5f1UsFwqjZ2T\nYas/Tood4jgkIGsxpmcxUsoIsz38DMLtvz2swvL/mJC3IEjPIlMjF2WH/qoc\nS8z50am9KiQ1UsJGC8RHL6lRyuTWuWiotKDuSMY0A2hnrqDCZ/rgPX2O/Gl0\nmruXjlj3jdKn7T+vjaK2HhslFXv/Q/By1Eu8KmbmA3ux45yxKDszTlqnYFZs\n7SmcHwtzRMzGFfU8gWjyA98dCpfPzyS/pAywi0n5NwBfMP2G8YCMHU9zrh79\ncgmKKEC3zpRy8scVySQ7/BQRX41I5NDb0DJo40ElGnmXZS4cZ8PqI8TdU5f9\nTJhqydoMxazx5oFyxplgg+EQt3+Z+bBWVVrOG2Y42+W5Fbt/cezDW8P1OomC\nmXYEQhO6fT/moijHqUJVYxWeSSQYgem6Kh9Y5wTVD6XvtRbth70K/mdrSvrS\nEzoijvwz6QZ3Zy8HpV1YypljqICVQMGCvzFHuIva+IvipsArVNUr4QJWj0WI\nwcMOOtN8HbRVbcCC7neoUr22I2+9E3O7HNb6HIFH6UlMrbvkA0lC4Ur06dHC\nj8q+LuPYXA7sHX/sCiaxLTrIQuvGbZwdCzSq4MLxH9Zov0OgXBRxsVZ6jVB4\nywkfi5OSonHdJx6Lf///xXu7jRTuvEMamCUCXAwWdvcwVTAKuyaWyesWbayq\nksx4\r\n=w9hJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF1gTKMioAmWHGVJBIKeo/wggy+x4AcKieYem12PUEfEAiEAg/ysCkov5G8JCgFCQ/JZFu6CRvne9ZwgWYOJudPRnGc="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.32_1566475123534_0.19296033341314178"},"_hasShrinkwrap":false},"5.0.0-rc.33":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.33","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.23","nornj-react":"^5.0.0-rc.15"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.33","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-KNdSMoSeI+xI8VOUyijRBWGgpM+k8BOnWHl8RaNfIlnfSFKBEN72GlBjOXDEi5ZwIsgTW2jCcrVKYlqU6Hl7SQ==","shasum":"751e02f7de2c6af815d283a6cf702da9d45ca54f","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.33.tgz","fileCount":12,"unpackedSize":55656,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdciydCRA9TVsSAnZWagAAYxoP/04GRd7gXGtb4pixw3PR\n3PIhZ1uozz3N+4uBCK7y73px3lk1wj3yeVNh3QhQW2i0xbnfdR8UsIfIGImc\nLeVca9kmyUdV/vO2IaU9RXF8GQ1Y/HBUGy8BJHiUDJRgyBjW1MtwB83Oc8l1\npIE4QvjqCBaBwfcMv5J6WNaaBMkW5kfDGKFutpIKWSMyqGTsKqS5Z5gN+fN5\nXHzQUjwz+XZBftX/naonf623H8iZ9nIr6gHt44wGIg+ly4kucEbUazB3sRhc\ndlixyJWN2vhRmCJRek/vZGaWEaCSENw1sWwkfzo8JcB+nyOO4W4UkYFU7FcA\n1nyU3DvBeCtAyOBWBgAUi5I8gX5Qx5MMDFgLLZvb6Mej03JeIQGlF9IGv+h5\nL7IRcxLZSL8jLchfVmlQW0IReCC14bIbGUwCW04AFT7qV7BRAMoSGUMs9du7\nuZ/vBfHvPChjMZGqeGUVle/ZSKzFttyhVNvw738BALT2KhTg1nYIxTIyybeM\nsr8yo+XUCJNhRuQQz+AmTnux3kQG1QpgV7Tn0K4sB0+5P0EyyNo7VdrdC4L5\nWrBhIGkfVhOV0JYOkdNuhUIP6PJ4uzQ6heIA9MTn+Qn1zgyHaErt+ET5ytsw\nUbkSqPm2pFZ+1RHD8Z7uy9d0WK8NtxkXlnMATXl/wp6rkwPEtdmsezvyJKuk\nJajm\r\n=Ok8G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDlG69EG4AIoLdlOfpLcu+waEN1owCGhz2a/SnFRb6XFAIhANjgERwHALHltHVe92fNb+UNKvaWlUhCGOuCcM9PGvlK"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.33_1567763612884_0.2977830356716238"},"_hasShrinkwrap":false},"5.0.0-rc.34":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.34","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.24","nornj-react":"^5.0.0-rc.15"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.34","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-IWYE7RRGPYpv8+kSrQwddsq6nyAtTXdOZ+U9lWv+00Up3ThTT4WS9Pi/Q7wFmzOAoOWjpq8iWmLIqDJqNYbE7Q==","shasum":"27d7687117e5f4f1f9c7e9754d72e0a69a7d729b","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.34.tgz","fileCount":12,"unpackedSize":55656,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdefGVCRA9TVsSAnZWagAAfOEQAJRhjEVDXpuBRZneoas3\nqYqTbsy/ad/3kIl1BeL8QF07PtVB9WDBSeGzAa2eLWflgmViEmspZkGJdwC4\nzrkJrGkmTZhw7vMOKBZbQWL/3PcZ5eWTngYxuSlQtXUMlgQZQwcd4k+y7y9U\nMYcM21xtDmchejbszhyxu24xbf6N+IZFQQcfxZdxSHazUiEOD/GUE4OjrHj8\nXSD1RxT4PUjNMKiIgpVeYuEpn9LRDFDdK0Y8k6PK6vQDIm3i6cuGWhOeCMyY\nmaJvyqoq/9by+kbX1QpxqG50WpYP6fZNCRMODx4KGAgHW4gHondLglq8Mlkz\n4JGdjtRF8ge9a2YKP7W7HgdpL/SJEM8bn7ejIh43AXKCwGMT59B6KcADkihx\nEKWeE+ylCLMcwM4lOX+iDJ9CFm5gi1jP15wk/7+1hN8iIaQL2l9mcrm8X8k5\nWylfXY64xOQLVySLKvVfXwttNLwRQMYil9lsHM6oUFntFtoBPufNxNyXTJxe\n3nGpHXQRHmXnDd4ufvvUiDKVH5b7S3A+O5mZMIiCZy3eiFwhsODId+ut1lL2\nbdZHwvGrX3Ar4/UnPqJ5MZuohEfI1TtfbxNJXndAky77B3E7mG0liSHqE7Oc\nXXpJhHepWrrFkfK7YVNrEmd03ycGQYiBJ0jgw4T5tWJ7Ugh/AcySd6xho0K5\n/DYa\r\n=KqCA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDTmSzV9Z3tGrCmZQt97gOvV15ChH7efLWnaV14fF8t/AiEArRQhemiwvd9c75FqG6QAZXimq6WE+eSHuBEWbHwCeT8="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.34_1568272788347_0.8036116481577531"},"_hasShrinkwrap":false},"5.0.0-rc.35":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.35","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.25","nornj-react":"^5.0.0-rc.15"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.35","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-Z+dqkNmtblVQoe5OIKkebFBbZrI4VRdfk3lPlBWpusQR/U/hnWLa3Rpq+rikkJuzE9JSCrbZ0kRG9JWgbuUBDg==","shasum":"874ab1df5cd8f62420b9a3cd0928937544cde570","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.35.tgz","fileCount":12,"unpackedSize":55671,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdfwhpCRA9TVsSAnZWagAAqxMP/ig334TjViqBv/MEWSBA\ny/31dwQd3H86+hOivw75OZTIrHF/G24jLVjjnCT2NXK+DH9ikwVZYcFWxiHc\nTMg+Q6bX/Q1OompgNtERoEpAMBpa8zyhtGR/GagldFkzBqsxCEGsG2AU8Mxo\nzA01dXPafalBIs70yUESPWfizW2ukjvrgRiFwUuTTV3uraJSu3DX+wEma7zm\nOdntPfu9hY7UXoqzi7dFSIUmcXWt4EkilOf691ZfW1LAvAvUczJ6EYit4W5C\ncdp7/9MnDh0GaYDGzMWAa6uXhfVlugXftbwxq6oketc8STwVRFjQQvOWbld9\nsfQT0sh6qMSEpSBYEMnWF2zriBRKYN8d86sidwHmZv6ri1SClpmujhEm2wyF\noWfMeitnCuv39ylyINwxPDS3vKNBNuHFs02xJTXM5v+vpeKrwqaBHDK45OlF\n/2ktWQ242U7X9hS04vOjH+KZZTWHpa1Kpkxxi/0YK1BNRqOnwDYV8iloGevS\nhZjqV2GFZPT02ckoG2frjjwA4/2Wi+JG0fHkUFeikOqlRes4YDHUaih4QMmJ\nXv2O2L3bECZHZe9YBOyjdEpcFFCYswh9AJTh665ktyGl4Xl+EgFVS9OkddS2\n36JhlKAFmuXcA1efcMg85gCb2ZQR6aF8rQPesabmGCcRMF0TNgk+9DRiSiCY\nTLSg\r\n=G7iM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICrcIFsPdzuszRCWRIdeVg37PzRSi1fQDmxgZpZIqrbxAiEAgJtMeSwoC9nN47kLHCPmk9WIBKj7tg3BCFb5w54oEl4="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.35_1568606312852_0.11868772864888166"},"_hasShrinkwrap":false},"5.0.0-rc.36":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.36","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.26","nornj-react":"^5.0.0-rc.16"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.36","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-PiTnWNg4xrHFe53hmtF0AX8AVB0MFjgR1RbbkkYDxCLbMp39t2geLXj3qedQTFjWGRpTwvtidwKfeu/cvKN60A==","shasum":"3deed1388abd73c68f368efd2e3806262d58097a","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.36.tgz","fileCount":12,"unpackedSize":55671,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdp98UCRA9TVsSAnZWagAARLcP/3e+72c0HmKthMo2IBjz\n5OGxAj4SXLNZxobpEn2aiSo53o5/KoxnEwstNlMQHIGL/VPzXaFypt8l8/BM\nJe+vaSJUqxc/w2Ya3+i+PLUErCrpEZF0JhHngbF6/btuu6ZK1VBtBzv/DXrp\nsQss4uPjtEb5r5p4lbuI3vioKuryWcybZKJ2j+LMDvql1z/Ynirv+AZjbLi6\nHmRkT5BvPFjpjwOmh6WIi1sjJkt316ARgzZwpZN1nnqJtcV+MxmXQ2klOB59\nCDfsaWoryNWOhUf7qZ0t5QRVKqWd1XvcDfxnRfkxzqxKE1Nee0+G88CVFSnA\nHARYefGM0QryaiuF1aRo9oW+Pq4rLY8kS7X+4YlAEMNeH3xRX6Yu/WUq6rBH\nNq+cxYW5vLDyxNaCfRFwCwKBkD1Yqufnze+VlsqzrSSoqAUXv13T7wd9At3h\nPLBNJ5SMt8WlGG+Q9rLaZXVu9uPIwJO4CICYwubPkrPfB63Wj4D4VaVSkahj\n0/sHdLgqjXYmfDOJ6y6W0QCv9YImpXFKmUHYNGu2QvFlIQ+emRl73F6wDKVq\nz7Lkq3wy2Mcl1PR79Oc9nwpYrOsGySqiIya6E5pdn6Ss5qr7150dIn8dyCeg\nrJtLLaxLvvesa4XzcQQq4fYUXIQKqjMOAC2jnFcSt6nzdrW9ppwzRoRKbWdJ\nZ+Lp\r\n=sNyz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHNmZ57Bv2yhtxYI/XM6fKwV6vfBEfHUQdnFN8X1jXP2AiA9UsorK0w6QTKu/LPCecuCLwbYs7jVkO6CYnHqpzic8w=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.36_1571282707345_0.11842120956352797"},"_hasShrinkwrap":false},"5.0.0-rc.37":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.37","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.27","nornj-react":"^5.0.0-rc.17"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.37","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-BBWD3O+6ssdP1n1KB+qc3t42ci3dzLBUKV2d+P9R8E9q6T1C+3kH0DLTX7HxJuzt5IIx+RI4HvU09nRBiv0G3A==","shasum":"37e9a3efad1d56e560e151d6785e47fb6ff1bf16","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.37.tgz","fileCount":12,"unpackedSize":55671,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdr9wHCRA9TVsSAnZWagAAOVsP/3Y4KS+wTd5wjG6YKWKp\nl4GR2eIRXJkvTAimNvgNvL5zRrMDb618Jj/Cw1rdcKLW1EaQinXRfowzrG0G\nKZqupue6CtHu5jBW/yMx/r2tVOPKZD6osdJc35a4QZ/6MaKwTvMn06HbuiJv\nk+iTO6RY3Uf4ScfTKO7WqaNur9varPk3h+ViGrmkooX/fB4xSqm9ShI7vrOj\njj6YBWDuRDHAYkXVkg3KjMA+nzFAArtBISzBCSSRMjxISGMDlmMENUIiU11G\nwa00fyjLL5URi+Fu6rxvcYK0uTvVmyS7I9uAW34g12x4kvuNumYFUQ2APILq\nQcd4D5oSftOdUFy3FwZU8BQXVCUAWh+PbyAHTXdePDu8S5APtPuvwxtH+RBj\nJd4PpJP0fmf/rcaj9czJZsx7JGWAyKLHcTXJrf6T5PPKL6UAAY2EFEzFB0Ik\n5BfJ3qVHSAGCLngPGfzgEsgQ2rbUrZ/3joNI9RRcEhOsHiS85gWOsXqhZ6VA\nBTYxo3hum2jHxzEwq5vHbhwZDWVEV0vn/05xYt2aAtbAUYxP1FEs2ydBDovJ\nzXV8QaadiFEE0X2WfK3ksozyY2HVAAoSehib9j44M1WgHkvDv0lhq+zl+6pD\nQ97xikeBMl/Cg1p3W1/6AJXK2v2FU2O1n+zIoM1mbhS6oW80HsC4a8pIL9ho\n4cgI\r\n=bKGu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCeW3T9c8bYpxTR7r3Jo/PEhHS+XPcKL25wUV9K25TIpQIhAPfiUeU3hjLslDQE1OVviYUjNZzYx+ohSJGG7ATllPdg"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.37_1571806215299_0.46611301981269393"},"_hasShrinkwrap":false},"5.0.0-rc.38":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.38","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"lint":"eslint src test","test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" node_modules/mocha/bin/_mocha test/index.js","ci":"npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.28","nornj-react":"^5.0.0-rc.18"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/register":"^7.4.0","babel-eslint":"^6.0.3","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","create-react-class":"^15.6.3","eslint":"^3.4.0","eslint-plugin-react":"^6.2.0","istanbul":"^0.4.1","mocha":"^3.0.2","react":"^16.8.6","react-dom":"^16.8.6","styled-jsx":"^2.2.7"},"readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.38","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"dist":{"integrity":"sha512-6usfDYyMlu5alV/zXNN+w0CHByoN+1Fdr+0Jv3NFzSK+6EPuHiPu+wxozcBEGo8OQQaTsPj7xqqsqmEfKkMjwA==","shasum":"23ff150c3c9a6fb0ec7d987d2cffbcc9049fdb2e","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.38.tgz","fileCount":12,"unpackedSize":55671,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdr/iPCRA9TVsSAnZWagAA/gIP/3/n7QEIYRW/oUG2pR0L\nX1cRU2n+nMRaD5zW+YOMozwKF9/wQB9pHPE26Nyl2xlne7UTq8Clr/3Ab/z2\nh9Puye/MPaa6VdYJFokGAUz0+fyHydkmXm17bi7b4/L7Y3nwRn7E2JX7/lv5\np6FOA1IW14ScGVnrIIIpd1dtEU7dds8EIV7otDBxKydRqnC3G9sdhcRMwD/G\n4zpqUW4Hf8KM5AXD52KVNWlsQvrQx1zAtrL4IQo3Qi9AxUpHPsougdbkeNso\n9rtLGyAO0iSyUSaRSWmZEIBj8qjXGt6teBoNjA/Dbqsbznuq/yxJ1i7P2LMi\nj9jNqbfYBg2rdXWNQFeMmDB3iH/rvnA8HNSBzeHpQfzcilZ8X48VprGiYZZB\nWXfYCMyQcFatzlksHGs+8WBQr2FVuTv+144x1w4HM9qozHzrVSziYaH1k6vI\nrP5rPqvCugEtOkq1Q+kt36jaoFAqM5xGpGgWY2KkizEmVEeFsGYSMFN3IxLU\n9Li5LUEiXv99nyagPeHIlLhaHJRx1OgFUnwthkBjUcNdJ+nH3qMVnAXAeN6v\nI19yN75VLtg/3KziZB0p0g923Il9YWKaW3F/q/5Ee7/TxHs6H0LBZdomLDm1\nuj36hnJMWZUS6K+DnGqvoFLyCxDf19qPsWKyYgNHL0WfgA7tKOy3xrBrEKMq\nNDGL\r\n=1JN5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICNaW0waFr6IKCmDBm72lUuww8nYPlY9qbyUeZ+QXcZGAiBdvjhEvVI0CQkWAo64sS/tMehzOPnLCqv58koNZ8cLfw=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.38_1571813518696_0.9590968205781885"},"_hasShrinkwrap":false},"5.0.0-rc.39":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.39","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.39","nornj-react":"^5.0.0-rc.39"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"ea5c6f7c2f9a77bf93f22a38a3062fdc688e2f03","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.39","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-Q9D4NCy/kn8MLGNSm3Iwxczt+sBVSW6G7a9gmoWIrkdvxUMyzWELX2dmXSboUIruniKOZRhly6mIAVRgkPvV2Q==","shasum":"9a03188409f79be597efb36c72f3d1f7c8bfe8c3","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.39.tgz","fileCount":12,"unpackedSize":56507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdt/Z8CRA9TVsSAnZWagAAifcP/i7dEpZTezmy4QLrdnBA\nuAj7FLeoA+1t7uZzaeJZ8IGJRUMTfktevaWoon378QxEDVoVetClxavRjRji\ncQ++7jwd+hnZTTVJBjLBlkFT/nC/v3kVoFXSJ2pwx4YZSiI/9gAGqrYFWT/S\nllfo9gEi/ZflikRH5f6UE3GgqPvb/H6e+JWstQtbQtxIV1o2NyZD2pAkFRST\n1AY/rmoI/b6C79SChe8Vp6gZpe6JXke61YjocY6FsLsiI1G88RNgavP6B1WU\naG2vChQEYdwjzc8xtOkaneYVlj5pyv0tLHk+MjrNBbGlTYMNGOl+I0CeTxDA\ns9pF3OWURe8EKNZEf7BwHJ7aj9EIB//NaPWNJg0ly+zhsd58eZyEu7XmmOhN\nHXUnFrFZJCSdIE2worspvtDPBtVllH+I/6QfBoOecgPi38BrMuFy9zWj/hsc\n56BWtw/7eFMbmS0VGRzjawyzp7ICnbk8BIYqq26jRT6uHt0KoppnucztDnM/\nXm3SwSccVOECx1xKc61Vk7iQtzFqJ3KT6Nc5qNGE+ATxU0tO2wlIR2OYildH\nFW9B3RzSLO0c1im5EsJPEkesLVZFA0k7sz7Dycm6ECsqm4NmrsKZIGZURKf+\n0OPoLu1hj1qHpjlXk83KbMn2IlfYuStBh9OD+26ry6EgUdF7NA73/sNUOkHx\npnHq\r\n=lRUP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD2f5FF5SZCFGTsXQXXK2fvZR43qrM1Y/B45EhnvN1AswIhAIXBXGWnMxMn995jdzxR4nqjxPpTtbn/h3HSdcbgRal3"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.39_1572337275767_0.7754113411988732"},"_hasShrinkwrap":false},"5.0.0-rc.40":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.40","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.40","nornj-react":"^5.0.0-rc.40"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"d9e2d8972ec486a6d56c88f870a1c8c6981b2166","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.40","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-KleZ1ApLxJ4IuUhwrk5ZSyZrucqIj3dGNwFwCCo7tcw8fFUrHL74PkPWlzEx8FOaY6PNHBA7HqSdbbZiav+W/Q==","shasum":"0ab8df1ff15a50835bd9c6f8177d1e175a662576","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.40.tgz","fileCount":12,"unpackedSize":56507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduRXVCRA9TVsSAnZWagAAWjIP/jRMFK93B33OSSJsULjp\nZo2T7n6/9daikslz/bX024Qg7OYYed9lCU+WBNUE59VRQbC0BRwlIFZJLz8t\nPkWlV9zMavE27JSnaLHhuz+9ly9VfP/UnNx7VHjyiAyiNxeNNKIvX5HdUc+t\nGB0CkQJyT/Su+Rolw3MohlePFa1KvLgMxZvmHqHfGoXo6hKYIa1KFKcJuS54\n0t8xtoTLhkVkSwodnlZdeK/mLhkGQo0vgPRHKF6QWNjAw4RJTByQDkkyfAPq\nvH3LH6KVFC5FTkEBFH3pdQxHyJ1f5hJxK9YjkmK393IjRt9j509Q3UhUkCwV\nNdxnuePgGjOjCQr+daoA7FKMyiS1/20sxGCfd9yTnDP2Qd+8MbhbeZj2RZBy\nvLbL7PMEQQXhF7+sv/A7rk9v92Vz9mMEat8tPLjtOUDs5xlscy66MTxx4SIL\n4jA1gWdELbXWIYlwZ6+2QbQdP/8fnsrsyQiTTO+pUJnZjbHet43lhxEk1Hgg\nkIyiFMwYLRwABd8SmfSaVZIdYUXNwD7HkLBnWKr6Tp8BdEpN2+KIaE+1+8nU\ny0KnlAVY/rKeUF/xkjcaaE49TW8qiYNETw9qDzVrelRRRlSVL1tzi6JQlvnj\n5uf5BLOdWbQFB/O2oMiFOI6ZqPQ9JWtzj/3v56dAfJp2ykookZn9Lj9ey7tQ\ngDMD\r\n=vGls\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH+tZJ3Hihk+ynGT2tkKoyEYt3EL+Hjxlh4sibC5sJqKAiBT1dQULt0aQ5NCX8xUcaw0CKfOA6982z0iYSQiNf6aew=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.40_1572410836733_0.8753905885728523"},"_hasShrinkwrap":false},"5.0.0-rc.41":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.41","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.41","nornj-react":"^5.0.0-rc.41"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"ffe7d846d60c690a7e04776b2fb81bd565a21471","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.41","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-+Oijrfs5BoRfXYtsZGKgbfxBrdG0aVW56fgEeZOVbggyX79bRcC2gRRq9lVBu9j6/9ziflpbheMwoeIRIn4dGg==","shasum":"321a42e0ac234779b4caff29a8a52b35be4fd5c2","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.41.tgz","fileCount":12,"unpackedSize":56507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduVIOCRA9TVsSAnZWagAA5CgP/2+glMv5B41dvHG5LBod\nMb/XbHobEkjqsyd7hip3hw1q4/tk7VN54rvwRlBvWoey4enMJe/N7XHw2nSq\nwZlZG0ia3QapO6ShhPLZvcaT0Qgfva0ot44RNTAJSxl48w1zt8XTdJ2nllss\nqHqalkkzWAnwcDyjHG7Cyw0CHZmkt5a0tV4EEKgKMZMmBTq2ScHIz/HqdbUd\nRqGx6Hy0qJOI/oI0ol6CKaZk7noH+WgGXAK4NwEtx8oIkxxvCwCr3+iaH3H3\ncvG97/hGCPEy4P5qonwWbWiDGp5w9wX+Kr8fEg8eDnp1ros28vYK9XVp4fOr\n577J5ZW6t/MD34UY665P3Sj0e6KmZm4CP3a3ug57exqZft2KQLaKbiQ6J3dZ\nAxITE4fFq4KLHM/PAd7xCTUNkl+22RPsDQurYtjJZIoNYqz06RPpi2EN6cmT\n9SpTvIE36Jye8xQlEzVIZFsZJcafc4/LQ6BbC4TTvKQo3npOlXsHFyjHluOR\n1bqlZpUP1tQmKXJVmgR51mp8z7yQxSQkrRhvQe5XPCdZG6uKaYzcFZe6KOo7\nEwrsay/K/4LqNVn5MdgiwgQKOb4fBHTrRjXeI5lGxEsjVS+EccL7TUR6DYZs\n+9MpuDpd3FhT0TAB2TuIXED4BBM8mVlLUKrFWiV1s99iYACC6CcPBufwjwvv\n6qwj\r\n=RWrc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdJAmae6vqQwTVidzjeYcxIHjSM5L1vEeBoPtS94NH2gIhAISiVKDhLFY9pvRcBUH/EgBBm4u9G78uST0htndIXdm/"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.41_1572426253434_0.3461787331547159"},"_hasShrinkwrap":false},"5.0.0-rc.42":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.42","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.42","nornj-react":"^5.0.0-rc.42"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"6162ba415563224635728441dd3ee6f432a3d7a7","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.42","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-gKcgtrSLtq7kPMVg5QGT7vK57ot+llGMLwumeoPy5Cw0n6+KzkL+t4uRs3Io9YkfLwgat9iBUUYrsfeVyZDeEA==","shasum":"31ec8c444784d05f3493f45233bcef1eb7cc88c0","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.42.tgz","fileCount":12,"unpackedSize":56507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdxURCCRA9TVsSAnZWagAA46kQAIyvd0uSK7CyVXf6H9EH\nstb0MU/Ru47lNqFw585zRbKz+C+bDLdUf+kEcJYNcQBN589wm08qH0UzEy6H\nAMmpsH6Iiu8wT0YVun5cmJp89SJ/EmNE4NjyoRyq6CTUe7VF4O2lKqkTkn4Y\ngHKbd7sEp3Dq9BBZrZHW4BMUTzEDVO4oCCjTaaSDxzTiE59dNMMuRIy9pt8k\n+DB5ewyoY4SuJ+4UOsZs78HjOAa9JLRwKEIjd8EV8IGahZHh5dgXX2vHGqfH\nZ9AmCqakbS4+RUzYeTRSpBjVst7EW0L4S0B1YDesFz2Y4i42HcC8L7yaRlls\nnId2xuZUnQRD+zlhuI4rbNXbeYR4RIDf78eV+t1wOqJKWqLR4rH/XrJ2QJu/\n+m7UHciDkPj/f75OTC6Fa0Ybol3hiQYmGbpW5ghbFfiPC6oXTwVv62Z6o3HP\nJ8Uj6zxJdqZfWdx6aLSKEMXmkiWqDurH48/dzk8a8/fTARYVFUq4wmbWq/mG\nV90eNWGFqBkNLvStW3IRiX2UrJkiYcGPrr9Vq26UN/OiHMBA6KkfcJreGeuC\nfESq4D/fyYQ7i3rqHo7cwV9ZzKRHYF82Zbd2x9LG7NzxjaGhxMk+cjGVhTUn\nzuD2k5WFpT5xBlCOJkhjDAqgiExkQ9qaQMNnRIMurah+X2z+qLOLrggiyAUx\nmcaY\r\n=nFke\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEE6KWCRMD/9yH/FI7GUyV01amboY7QXB74kIk+EX5/vAiEA5v5dpXcqd5czE9FyuRjcvfWtwhEI7Jl23ocBH8/kZrE="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.42_1573209153596_0.0947174555723338"},"_hasShrinkwrap":false},"5.0.0-rc.43":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.43","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.43","nornj-react":"^5.0.0-rc.43"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"af495239cd44beff9ae728ec41f57994c5a74e3e","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.43","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-6edkQvZCVVE3iNLTUrELe7ppQcx+yqP7yOnwAYYvhjheYGncblP08Z0nDZr89jaZ4dsiY0HvIfS57bFx2yGBCg==","shasum":"bc3083fc21dc8afa0d7d7c1ee344cc97e956e2f7","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.43.tgz","fileCount":12,"unpackedSize":56507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdxWCGCRA9TVsSAnZWagAAlKIP/1EMtf4t6UeI8SdUwpxt\n11l8ubyi3D6aRXo81nGJqwcM7SzG++de2DOqD1Zf4lrIxXv5z9S0YdnLQGN6\n6T9RmBbPmSK0ZCHVNPzWpr/u7o62y0A+uoxl2ZORIYAHdnCqdPyAWEQSMR+S\nVYaheCUDd1GrLyviL7v4YE9ltjjg04iMQg2QYxEw9vAf0SwT65cWgl8KBa/Q\nQ706UX+bO+qKajQurkbskCUHFGjcMrQ2p/jYKCmDuWpZeqiObPBnowZ8bgHk\n0kdVSudi08Qd7cIfemwGiC/Glf75FAe/X6xkDeiJjcnrA1VEQLlWZhfc9+O8\nEEqHaGNFq3QNn9EbSftEAuzHGmQ7x0Lhu54LHuuYyvDHebK4c52PIWL6rlNl\niVErxeH/HDmu/4BBgfjXq35Muzc29KcxTv0RsTb7syC6uevxCwvtvT3zSZES\nKcbc09uf8Jbh6EoJGSwpxdtweDac0ZX2VYAp3kpkzKGrBnnwYaaGam3rGNDc\nkeIJ4Ad6eVrGZD2rC7IMXfpWQ/IHUC1csadeg4rDHsTL3SOitb6AZotwS7jd\nAutVc3z1KZKJyK8rOdkrwVjBh0j1JM7vhwmhSvc/ZeldT4GI5zg0XNV7kYU8\njqpT7oHasuHWCjTuIVz1Bb4qBx/f0xbLVVY963Jx2zdGECibMYcMYO/Z0Ydl\nlLQJ\r\n=uvQt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLeyHejdy6T6AEE6jkpQ5luStfVt9Vy7KJLFKOZLixnwIgEkI0jGIz34AIlE26lXMX9mfuAIRYIwQ6GTbLLgBIjmA="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.43_1573216389528_0.8652676383617115"},"_hasShrinkwrap":false},"5.0.0-rc.44":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.44","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.44","nornj-react":"^5.0.0-rc.44"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"d526fdb7d06a29f03ab965c261cfa1539a0b1873","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.44","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-qYt4qnPHX0hQOir2sDq4CDgoKogFi0uug8DZNbPgF8LmGjV9ZNyQPQGP4bs6SFFq3EHtsvcP1qzmLmacSjQSzw==","shasum":"67b055e3d6383245a0263f943369218918cd7431","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.44.tgz","fileCount":12,"unpackedSize":56507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdyR6qCRA9TVsSAnZWagAAM9YP/2DOuWUB/ipYlNLBRcea\njTResqa0YBrsLOB9aTDyVD8+hMvyEgjSCdj2vA5riL4R4qcROov/HkzJJMMo\nSKK1+Gx2dHJEjW5qVZr9MQoIeVD4yueUQ7MoeX6NzN6xWylJMKkmUoPywOkv\nl2OyW3aQW6/aa8V6NBFEbLyxFxgJGKcKj2xTwR3HuOfOpDFyKDxgLHg2IOSw\nUz0gIW5rEB2+pNiQ6RS7SLye0UBohDlHUPAhSPkEhkEfPEzp2bMPH44RTdfY\n7P6oqZVFLnvGS8sWC8z4E4cPInjCuH6fj3KNSIyv3/7ullEDm4oDwLHh5poE\n0rUmtJvcZFemzfYbOgRmgEI8t7zbKUvrJsv/3btObQUdPHDyw4q3hCIFSfl3\nTgx4AEvzrALItPqXXR7iQ9/f1b07K3YCGCkQy63jOCWn50Rgb4kHYlLrMrCZ\nQasvip3wlkzEgXjQj6lnVei5+0jcb1gZ+F0YNBpNh7w9vO/d34GOAueYJcwh\njQUcQ+nHtCIPJ2Yz9hHTbRlhQIDvGsEv1HEhAKvebvuGrTdXb7yeKQvAFIwW\ny72rdVvmi+1KYjvq99ao5x4rnc2wRyVrlI50bPPzYF5iF8xEN6a8dkjg75s4\n31PXESLFsC43CKNh8hNW5JTFJ+UPJVTKtTepSsNITdZZdT9SX1hR2n2yjYlv\nRsb0\r\n=DW7b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFaJt2gjfFjXfhZLKhPNTCPhwExNb17t+kYkuRGUbiKzAiBIVWWK2cIKomiZJnu1kflYrSnF3HgFbpSzuKzv6gm2PA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.44_1573461673900_0.2911055116858605"},"_hasShrinkwrap":false},"5.0.0-rc.45":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.45","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.45","nornj-react":"^5.0.0-rc.45"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"c53577b980734dae8d67abd776e0f6685dff5127","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.45","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-dKpNQURMuwAqtvdcgay7Q9g1YvHslxjAv28Dev3mvKInXY51SyNBRPaGa2kUctZL7NT9w7GkHlW03FdDqDV8IA==","shasum":"16a0fbc13ef065638d30f9dc318730f421854318","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.45.tgz","fileCount":12,"unpackedSize":56507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdypInCRA9TVsSAnZWagAAZg0QAIzXdSLVXf9uo74R+grE\nrJmiwpljjbbpv+3+bhXKZruQudo82iLwmgzLBSNgXO8oQJQ8GQJ+GstzklE4\nEC6xlrRAhdn3Udi4LRl2Hq17YQAHXTBDjqs1tppwWCGYj//UnZAkKwxeioxJ\n89AaW0AUY4H6o2NowqB1U1JwVq3r8zxrfdIQHUdHrn+L0QbaZa/PXHMEXRh6\nuHbqh2oUMlczc3eiOCJ8p7bGEZoHBAHfKS20GOBt80GvXRqNjvevPCj44s+O\nqxv//c9R9XEvW+XIREu6YYPUKfjwZHZdvD0eQY3Uabt9Gan7AXNyOHeOztXa\n+pkp4biA1jRYXsUjHJ51kUHE3wFeej0jm5J/CTUi9NV1RCszUyFNv+YyoBY6\nNEcbYPDh4U+K/pvXXwE1AHzIPI+HJsi1imj6FZIFv0XmmpkcVssoGBBUPNpp\nfYYFpSKqeb5/kczS01bzv6SILdQCBuSwkJHqs4jlxd4ZqOEVC/8pYc/la9U6\nablJQ7lVuckGSvisFIS/HkiKI+6jT8T8bbLIi1HGBw1aYYYTexaZ2xrDSGmB\nTixY+ZjdR6APPdLnItEU49IPoiz5abq/NevvbdsjP+4siVDpwsy3fYWmiZF8\n/9fGU0jjvc5r/UpOtzETpuAl956pUSTWMNlg3P5T2+NpgCW4uFfmTvZYrMeQ\nYBla\r\n=gwqk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHr2SsbdEUIOyNOO8QZGj6yywG8qkUpUu7nDNBmtL+40AiEA1l9eEGHhUK2D9icFGhJjlwVHtYZvgAyTjpgQOb5ypeY="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.45_1573556775146_0.8220071071224084"},"_hasShrinkwrap":false},"5.0.0-rc-46":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc-46","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc-46","nornj-react":"^5.0.0-rc-46"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"92bb73921ad6ea8030dfab887cb3f5a5cc008a92","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc-46","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-TMQ0Yso/b6K9qvB4g7qzgpfwyDKtf1FtW9RLfA5Ho1ZmX41Zm4uP85f+wpVBh5dWG4xn75ebXQEDcwmBsIA1Bw==","shasum":"0ad54d6d34bc657cce36dc9ef775f9909899872f","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc-46.tgz","fileCount":12,"unpackedSize":56608,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdy/ISCRA9TVsSAnZWagAAhm4QAIpG660R97mdn72wpqfD\nyD9mMTI2iuD3+wYpjrP5eBkHZ0lTgG5vLhswhnK/2aKJZwBF0cJFnkJaGqne\ns8fsZBx1K1chxOorcVD/FxHPaEHBqxvxJfZrNOOybwIDXElfUbwxKQrsqFXz\nDXyPwR482kXTCoZkjtaQQAsBsDvY4n5pXgWZ7bMgIPO3iTcc14zmg2FJBmS/\n+qXS/5FR92CMukQfChhTIDUpD7ODvfLalVQiMthE0Wbevn8Uy1P7GRc0h80X\nIi63Bt39t77c6R/8Qk4QKCRcX9kRe7VedVZ2mPyEz9KolooFE5aU+uC24MwQ\n5XnYDo7dCaarGfTos/zoDEbeScOnRIoSv/3kf0HrUz8ZVdabv5Aj4jXIzgqS\ntvpGObJOy7ToJD51zKTFYjmLGAfihQESEr5fMNEYpVRyZFWuBMLPRHj3D8S/\n8S0XVqeXrz8d12qC1Hr1LpJm3XxrXaFsEmK70iVA5qm88kE/zzgLs+hGdF0o\nMGIK5Hx76NfJbbYT12gUJWG4lVa/am7W//sm+O9OhQPrpTe4VtMLoR4SlZ07\nT+nQv/mZ6ROqwPdiat6L3IktGt5O0mE944ZC4/JWp94yrO3DTINfnQ/T4H04\nBOnT77d0+iK2MKsoW1kna3PsgkkEflpLfrmry40mDVMCncDbY3UrhC/C7vou\n3wlk\r\n=pNUW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEknL9mUNbx7WF4RLC58zwL48B7EfKWV4fJg7WaQLhptAiAqyn2LX0jkUjA0SG9mJjzkOQD50j/GXnhD+KxBe4CL2g=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc-46_1573646866437_0.07971281243540229"},"_hasShrinkwrap":false},"5.0.0-rc.47":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.47","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.47","nornj-react":"^5.0.0-rc.47"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"0513415ce09e4f4e1a45cefbc1ac1d0e75754547","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.47","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-uxpmQgqh4DUI31HhjP7/BV41hHg92nXNIFxxDxXKv7U1ZOs0iJRMDrwlcBl/Hz1/cbfsUoFRghHL+n3IURtViQ==","shasum":"ed3092e91fba0f2fc66fcf3be128091b7ca20cfb","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.47.tgz","fileCount":12,"unpackedSize":56608,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdzmYdCRA9TVsSAnZWagAAhlAP+QAx+CSq9adoGbkIuRkQ\nhGGwovgBe9rP8DzlxEZvfIu4vBZHF0+TlxJVOGCWLd6VviAucFFfoaZISaFz\nV+jIEv5I6HJ8ZeUWRrWMER5tiP5kJcbWi/FLsuf3/XWxcke9KBEX1+zNt7f1\nQnlnpl6yu5cJ3iG2twTO06cTbjehot+KEvX5OuahtbCVGXZL6tusHQ0c4Dzh\n9b2Hs72SPoB15upXSxqGazArRhqFxcEZTk7D7PmVx4exaf5OAOmrXDytfUWc\njl8kSCv1WbJ0zjJ2h+A5YP4x+B+wrpkF+rVwmk1sf898W1ubyzNrhD3JVfA2\nYdpo0+8Qz9FUOWOUuY3/mEiFa+wRWBZUcshlpmnEkBp+9hE7PzAJfjIW/OZ9\nzie65dSwoERry7KHs6Smgmj7dxPaPixwdja58lpx11ZkSCZVYnvVROeGTFld\n6leRqFTxYMS0cliEy47LJ4WIimmydFQDl9aV4fN7fTgXXx+0HyX+lVyIX9zF\ndXwIJZ/sJkxxDG23bFxwaEfObn73pf4vb3VJOdCvYPf1cfMsXGZ0eI1O9zh4\ndKX9ayd9UvZhGBXkoSOuo+aGGFW3DMYyiyLsnzYp+djPMrrhZ99L2vicTl0t\nxw3eQp8FeEUeDIAmR0XwIsYbS1/SlSyv6kb+gQZKoSCWiOscP/Psb1ZLS/X1\n/pLr\r\n=UYFC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD1lP9Q+3kFbQw0/yqIjg3SfRAtrhJ/llGKSBlwhwudmAIhAKbmSBKGjpDEMUxm9lY8HPdGaS4wgpmc1MZjHhyaY65m"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.47_1573807644765_0.7876860584117005"},"_hasShrinkwrap":false},"5.0.0-rc.48":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.48","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.48","nornj-react":"^5.0.0-rc.48"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"3f2cf948b67c736dc8ffe76926745533795eb988","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.48","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-O+4hOLZnbi9YoR6IzwRawmNZI2PAPGaNydz3jpOmQu5lqh6qjZ9ZH7YEw055nAvkqjvjENJOcOaogIC+ieJxTw==","shasum":"1a417e64481681f97e5c72491f52d498a8ed13a1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.48.tgz","fileCount":12,"unpackedSize":56482,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd087rCRA9TVsSAnZWagAA580P/jntUMC4pf6vV6v7GatZ\niGrEcUn+CTvJJacFF7Kvce/NVSIznU5CZ2LU93YRbq3LgdzSgYWORtCip65M\nttHZAPu5F3+5wOQNLBN1N0mbbxRuJ1QWBIGzMc1ypcZpEKgB5qdSGba7ZQxk\n3moswKBQthZmXKyYbNWvv7JYt/h9wrskt2pmazhwfTJKWRCjMFqdII4lGQKD\n68W67kWVprJjRQwlF4Z71wF3U6SiYLpFeCOb0/SXylyp+oIQhqR0yYD0fKc2\nUUQ8AfzhbyR0NSpwxlLj0F8Dut2J4N1CXu4NSe9uP0fHlzD6C4dHZ62WdEoY\nEofF+lGr5Hwld4RTAEtLDFndG9buCZXC5+XtYALs+rJQzDd60fV/hH4Fa4uK\njUCys0MMje2snFHCA5yhr7fZOxhnh5EpJWz5FhmKKxBaP1ejTJIvfl+aI5Pb\nHPSjCismZhzNBbdRc++uo0lrHioobvpXVZq6LTaJu/qIm6P2BrgGjhg6codL\nnwRKdfXBui3PbVeQSiPG1lTgaZtt+8lod3u9pmDSrNlpuErgByTDoK2VCJZn\nkaafgxu1sKSRSlUQ4tg8MwXu7t4bUu+iM3WpIYDWkwuji6JUwb8dYGhO2Wut\nJYG9zw0edGtzJThN/hE5qU3BEB1soL98nsVuDmm1z5SyMP35O70NpDEPwLC0\nfdaE\r\n=kEEd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEoyDAgApV1vxW0QqoXuYeMYce8Btt3VmDGYCOnZd+JKAiEAo5091JWuWfU7Taqb/qNd0w5kpLlc2zBh42aAcEjfwzE="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.48_1574162155149_0.6159682769375538"},"_hasShrinkwrap":false},"5.0.0-rc.49":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.49","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.49","nornj-react":"^5.0.0-rc.49"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"1ada6d9bd3bc1348e93f5288a10fca6ed0f1c300","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.49","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-phiK/OslwsK0uwz/jhuB16tNBg9KOQ0KB34dc6Na69/SmNgrsF0eftS9KGyOZQRRyIj2Gu8VDnxcVlPfPIc6Rw==","shasum":"d34091b6d1e9331dffda24c6d4af0cb46ace36f0","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.49.tgz","fileCount":12,"unpackedSize":56482,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd1SF6CRA9TVsSAnZWagAA80wP/18B5Z2ILUziLq++MpNm\nIWKpQvf/xsRs2T6eItI1opoc0bf17WDrQOue3uWGAAV6toQxY+N43eMQeQ8k\nxnOkTPxX7W3AjWkz0RoJTa0sldqDlwBiwYh9LHWY3U6RilgbqoEiABwiyust\nushsre2g75fWDbALcThPxikFUZng8sfl4SCrjm/m5WpW23UOE7n9QneG7gAw\nSMrA1+5gWC3NFP3Lii1hbVFTjRMwwt4X86UyfuTkbXtjXdwPMFNWp035C2Hr\n11VimRaC6Cq+fJaNQKfJXxQ+H1+X4AZ+60+snT1MZ2hutYyEDoi/1u47A0TM\ng4XELNnmy2jaipwF2sp8LbNmCLVZdYy79nBVZjOmd1yDvNxvZuE+ZKvCVCs8\n7zBZinNZ7M3TWKHRQ/aXTAFW4pkVfOLVu+QnU1x6M+QOm1mpoWPgaY9HJX3K\ncHAQMCOlgGGnUSYP4IR3N6/tRjXtjabX5OHo26LV8Ac7bIa8fWnJUz+g45iO\n8J/xcy0c9X9twynHaEAPEBmZ7H95fe+OuNZ6KSsPn65ztu4ktYejS8RJN1Vu\nuq5ZkTaaZnnCJzaTG/ODoWiMSLQKKpGC2eGSpOHgWm1sGq88thOxKbRT6Rov\nazjaDHo/H5ZzFblzamtEiVmfinSFCJptWBGf42dK7HaLCW1S3flMt7yYOXoP\n3KeN\r\n=QcgC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGKWaX47TlYbsirUVL8iR3M/571DfZ8mqMYaJk8hXasxAiEA05btBJ7YnfQ1s7IgXYTqovv7cxBnnjskhzwyRbGy2xE="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.49_1574248825507_0.4329077592720285"},"_hasShrinkwrap":false},"5.0.0-rc.50":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.50","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.50","nornj-react":"^5.0.0-rc.50"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"2a3bfb2bc20e30a643caf0501eed3e8c1d428e64","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.50","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-8e7dTKFVOetwopDZyIDK381aLG/T+JtDoHFezCUbAjvffAxM8jpjPPKp7wMwt8U6RCPll+cWHlADb5An5kx6jQ==","shasum":"d48f27795c14c0886c35f2b878dd3a74c5250c2a","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.50.tgz","fileCount":12,"unpackedSize":56496,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd18ubCRA9TVsSAnZWagAAzKYP/A2ANmeWB2mHTWrSSJjZ\ncS9icPSjkBNySlpzdt7v41CivY8ITMVSkREvGJnbD1uNgH5Nsovyx4h3NLz3\nDnVp7/A9ANEIhpj8Q44YIlhPg9qED1q5dUbCFwU8WIMwEAVoGGBxRqNbXEvX\n2b3VfYGDTkMY2NOluFxKCo74/0ci1x5hAMH1xS/GeQeTto/icZnZnGGYcWNN\nrsXgKx4gM4C1WoZmuSxkfCU0f34GYXkDyKaCBQ0KssQHEY/yzdTFQS1ll7+7\nLMvoR6Ws+kPNGgpJ6do6J+TnUb2TBBJUmlhStAuUuxMsaqy43A1kDZkM0Eyr\nWGTk67qAEPzFrKbUy0x982imgAd9T9WwXqBWLQXiWKFJiZqpnNZ/Wr40wque\nPcrDSrgXh5++ssXOzqIp+rsUrQSNVUhRTpn81UfhEVLFAe689HOGYSdr+bq8\nUR0Lscp4nrzzQm3w8zOCUmMHx0Z2QWDH+ShMU2swYwfA7d5AQft0f3NV5j7K\np5X+AJFwldlcWTeFgPHbQPtGrrf5wvjjUYDte5+BQ/CzeGPIB8zDer1GhxFu\ncgnn8XckTZdO1tnwha5FL49SXdmhE2X5UYDH5m4jMEeuSgy4/Mbl5GMT+FWd\nAykVfHDVBuGQfBmTmil7BEHAzQnFnZOZmg/OIHOyS3bl8n8/g4rBX7Zok5ty\np2sU\r\n=S4aK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC1zMm1vcxW8H+2n5F1SCRdxyrOF3Yf39tKVwdrgIJOwAiEAsrKxLkMWy8P1Tl19DMxT1oFEQvk9gIJCBw+Dj3cMgzY="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.50_1574423451437_0.2388286881616104"},"_hasShrinkwrap":false},"5.0.0-rc.51":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0-rc.51","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0-rc.51","nornj-react":"^5.0.0-rc.51"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"9fe330590856f957739b73d4e132643f46cc9ed9","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0-rc.51","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-vdIQYlVAVX86gmUGcQGx3AFq+cPW7CcXP9qXXL4MuyZoRjnX9JNuICIvq4jxKjccwT5jh4uuqBU+rGb1YVp71Q==","shasum":"a80c8b9b2d455f3ba4031365f1dc73ae0053427d","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0-rc.51.tgz","fileCount":12,"unpackedSize":56496,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd3Q3pCRA9TVsSAnZWagAARrQP+gJi2IADwQedo9WaaOGn\nh1loserInyzFwLSFCeFbezXRbqMZkjhNC1w7WIlcMtf9WNK+CFod95TkBouH\nffMCawWMtaAOsSX1c4d3WJ1HwL2s0UpVVPytq50jopJZyvRlVLaNyWg6yA9o\nLfhUGJCbrUwfnZ025KvJe4x4l0OC9t3bDYQabAOTcfFE0/e7ugL9Ukq738rE\npxn7oFQ/3hnS+/R8XJ973pA8C6gRuziaShJZQOhPrNYWP01vCrJE6Ye8KnGW\n+NgrM9donCVq4lVqQqWYRkfWM4gcVI9/jzTQ22rkRIWmQqz0mdwkuNaK6GqX\nzU11WIidYRcpo3DcwnRqqSh6TKQxVuNcRuxVkyqQIjGFvC37gJ3NepdCaP32\nLyM+wllQmnkt9eieinFb6XeT0ZXgKlYQc5sdxJItcjWvLTNPH7c907kNkT9k\nBcWsOnebuMF/32Y7I6EaMI2ZIGXtJQpjhkyaoVzLVpmPjBSMy5g9eY5LTBEZ\nCnBWZeLW9RyeKR1kAtPSQOFrQk0QR3A5MkiHrdSPOd5OQd2lR/V171gvStLX\nbINtHf8GiTBoRRkFf64bG/bHYSsVhUXln+l2SFxtrCTNjUteJcQLtRmuRf/0\nYjJdD3p6M+JxbbECLeoeClEZHyXE74UAjKc4AMiDyBgkxB2ACQjNiHwEpnLW\nDwrD\r\n=eFXs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSC6P8UsVGZZi47LvWcoRJ/EQbrrzC3jiF1wP9wPPsjwIhAOK3EBxhw6j7OZ7OGVGypp15T3ekyS2cvqqYC+FD3QcO"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0-rc.51_1574768105513_0.596991882096523"},"_hasShrinkwrap":false},"5.0.0":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.0","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.0","nornj-react":"^5.0.0"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"c13f4ee81360925fdab84c583671936934e8c6d0","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.0","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-M0HMQYu8IKDYIMzTR3NB+3VGuUpuLjBgXJGAOc7vVOeCm8RxQIAcoy8FSZ7TNbfPXpgYjYjS6/Brux1nn2L6Cg==","shasum":"de78c1afec8762140825ef9dca4cef9e026cbeb8","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.0.tgz","fileCount":12,"unpackedSize":56559,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd5h+KCRA9TVsSAnZWagAAjDcP/1CRq7EeZjHCSM7iKp5o\n7Liw87vSBSFELAxWmvpij929nrXy27ivcYYzw4z+aDAIdm2rvHPk5YQRNqlQ\n0c8eN1i+9OH0YuelVoV+zejSsmDv732888+DQPsPSpGYNKAfbnFOJDnOo19c\nhmBwJtCFxi+7Vg2gxQW//t+6ub+u6M2KEAeWr046JVc3BGROtP4e/B9vQgu2\nhUh4VfsCTGbqwyl6bd8rFqiS73xiYKvwO4keDLNc0AEMMQFYmGkyypBj7izu\nOd7rC4xPamdh1aukpJHkPa1r+BoN3fSr5jrWUe7hTIE4ylCPd3cfsZ5NtAK/\niv8cXCuHJ7CeBJxRF102c4gaVVLMDXHuCTU9RI8JIO18YmoMZ99/BHhr2wMa\nmg07Ixto0GuSMAsa0+vYKb2sKRNHCqBN413kD360uxv7KvWFSZkgatjmg54y\nJ2Q5UduZ51g1gPAhp5eQala1qLs2wozpWhzM5y7NpvUMTkScFtDtACZYtpBV\nOZAjobjcJjmCnQ1Eq0AoC9x+ywVG+GkuJA7jR2ylAL1jRN3KCnXUbOMIyY6q\nrl/8BRNJanvSZQ7TcRGzRAaNF8BvNZ7CHU+z37CVAJEsImpH412g+ds1FWQV\nITLSf4uejSlAIFaxukxo5M8NjItqQ7k26xbzelJldQNIl172Y+uYwMv4oeL6\nE9G7\r\n=2Ld5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyUcJimuIe2nM3nT5TuS3v7+So7qFD76WtNl7e8N/4TgIhAKpec07DEMSrMccuelapKbPv0p4v2mkb5gKobRhCeq++"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.0_1575362441946_0.09110119201894529"},"_hasShrinkwrap":false},"5.0.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.1","nornj-react":"^5.0.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"d33990e5cc956937201751e570311a57f54074cc","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.1","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-3mkVDfGx639JpqqCJ4+VedGSLBVzZhJl6k8raEUWOLsKhwErp13gGCbz0fUBju/nLrzFxfl8eGPAPMy8eFRkiA==","shasum":"d2cdf50149820a61e3337717b08fe393a65a3867","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.1.tgz","fileCount":12,"unpackedSize":56559,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd56H6CRA9TVsSAnZWagAA+DIP/j2TPQpBPWDVZTXkoLdW\nSvv6Sot5xxtZhXYwgZjB6HFWhvSUzgo5XNs9Lp2WW8IF0q8ZB6YN10nTIVap\n+Y1w6TvNuLgg4l+om6FVljgfr0QbWM1UoR5JF37mF6u90554v/9+xvo2ivko\nbG7sM+f3XysBdrPHqGqfZfD/qy3FpmS93hWofiAvra0TQzgFdL/3HzM1ANi9\nEWjVnkkFSgj9ynBhWDjN/ldV0PAV19WpDVOJjwz6Vuy88gUahavVRqMCczLR\nKXc7+199IyoccaAt/PPBFWdwY84h1aauXXAk9lOtNaG7iR5lXuXQbJIgfNDq\n3xd+YSG947Gh56vcUF/BKBMMIzxkkNoxs2tsne9KfjMDm/mq76zWOTJwis70\nm5O6G9kK6VUtgZXtFtyJhOaOIeEaa8pnzp+B410Lny0fcfSyiudxEwx0j+AV\nLuEzX/g/tWGqv3K7JM5j5aG1Q6+bbnC0KZ8lH2uQkSFK7IhaEG2EB7w0Y3VM\ndaZHni4JLpTwgtEVq+x+UJQQHJEdTxDDazCV207ZIkeCQ9y5heFIegk8TPzo\n8QB3Glx8HdBmTXMqFzI0CaE/du/0YaxVn3Zy47hFoTL+1NYUlr66Jk4xwp9b\nvKzIhb6Fcplo2Gt3rHHpN7JKRSDbWT8Vr6llwqa8lSjjA3F483KPQYMf57mm\nFaUS\r\n=xZdD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFeFlQYBsduy4KxU4JfYpOaAjsvQpEdqrAkALK/S7LlVAiEAsUkxJ9QZXvGSP+xVDIUmhj+HYhgxwa9VCCNhU3YRkN8="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.1_1575461370417_0.6702564001431892"},"_hasShrinkwrap":false},"5.0.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.2","nornj-react":"^5.0.2"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"1dd8a244b9caa32a770ffc948d82b962b88ce038","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.2","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-5BOXQBaG7z7t2rFhM5VQEP5zQcVrvnX8W3ywh8vFyku0KuYN2jPkB9ytUcFvW6FBCcgdM/VqLnxqDBsi4OkLnA==","shasum":"ac02ff452a8f9237c1673cfb8eafe59129da2158","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.2.tgz","fileCount":12,"unpackedSize":56499,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd6c3PCRA9TVsSAnZWagAAk0AP/3zU2A42pGBYMcgjxCt7\n/I/rjEwAlLp4+k+IRjf8ndHbaqYTxAv1QkJiVaDUjUh6LatiZlxZ9YL+SsmW\nKBLa+AzBLlKXt1tbAsUNaeml1VZC+wwHZNVjPmxMdorVwV6/RCuj5DfI/cga\nPa9XDd6cf4PVpB9o0/PyHLLvNscWNQKRls+/9WxyveuWBWLGLoc3lQB6todT\no4u7GkDPWe7IEF/WYbydaI9arizpFClYpKGlmLZYR1LjKwbzu7SxO64Xy3Zw\n5t3BLpv91pSnyPzx/pXeJAduivYkqoNy7WAdZHlISgTydAh6i35xttJQKGhk\nb9fQFpDXREuesvI7gVAEsBb/ctypl/5xQ+8L7m9obl2KE5BAgpFvGv/VAu0o\n+xPkwouWFZiSMHWpRodjUTWkf3BeosAfR2D7rrTQmgx66ay1AYPf/tI6yAf0\nmW9B4mzRbRl3xUqZjVYjWXWcMCn/7pkVpEr5m3St6OuLQ3lXtd4pFEPgzYzK\nmRii/2OHwSxNchvTRx4E4xdKTILxLE5ETegdJn+f9h0jDspLEoDRmw4jWU8X\nPL6kASO/ed4bRm82q0pEehJK4RDVanaeKg+OB8+yTc7i9JVcjvJFAHiVMWWQ\nNWWF7LwND/xBan9H2Jo94gcisQCIPJS31aPUisQ5I8fB7UxxOghJsKbPvY70\nYZxP\r\n=q9k7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCl62a2CAwIP8m/93heceTBNi6fukOfkPN2aPNysesvUgIhAILEatAfsha/oUyyKUDnIBRUAoxqdweBdeKsawPJ/tF1"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.2_1575603663214_0.18818324598004454"},"_hasShrinkwrap":false},"5.0.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.3","nornj-react":"^5.0.3"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"b2c0412dae0c573fa188894d05cd874610a4d788","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.3","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-RHfDL+DeqzkaCNYXQ/yiZGyC2qzVmzlyOshjAo6TW0n91nZ8d6PBt3UY9sL2yuzq5yjW+ObmNM/YZ0jFnSr5og==","shasum":"7582209029635fef5e4084b9dfe5ab50dc6cff4d","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.3.tgz","fileCount":12,"unpackedSize":56460,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd677wCRA9TVsSAnZWagAApbEQAJNd+KqR6RnbxRd3pIxB\n8NiU0azPbdEV9LA3sRBh6V9A05Rg1wUfc56oMKIpmVWncl3SrX/Bt5IUiUI5\npLsxiMWwcyapbBRS1sim/RAvYeCOQN311oBhjyhlQu/s+poow/+0DIS4BtzG\n1E6lyhO0FfUH9QzlbXElJLkctZye11PAZEaBByUB/Gxb6QhaJhEv9njm2UPy\nQJOrtglC5p2fUJEaxb+1uuxBB88EGwCoKgf6sYZkZjH9h2CwxXhvOnYDO9bw\nKmxm0vbCb8nvYS5qXSd3sNIaYafu1HRUn+TGKgAZORqHbAeIe2HDEn+5He6M\n53TbcdFeIU5yUqJeo1/D0rADV6o8nJzVcs6/4yC0q7Vt2c+pCQ/5cDLLBvMG\nowsCIhDYDauMb7kfLeRPtSVvDwZripmFdIxcg5tce22C0une4NEIZWaHlHIS\ndHWrpzP649gcTvFOHyFCX7mlkW9EfnfDEYJUyFOIzdJZlqHl35+oYPgxbswY\noi8wOaTD+S4/jIuWm08M2GgYZshxgIYJpZBVBdamWk4q+5xgzZPrcbWsLFHx\ntRbT/S19ns6QZ01zkLtGI8ZzVkjxEUDP/rcSfFemk6ceglHfv1okPABniisx\nQRNo/fzF16LWX5Z1XA20P5NeY6rI6u8J6do/xFEg/Je9sN9VgpzUMnlcLcL+\nR/M3\r\n=y7By\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE9yI+N3M4vzxLf5SHJG0GfzFJBlirpk6YQnGREFwGsoAiA3BoT7rW/jv3EzvxDp0lp6/sgeFxk7w7yXDx1mNk0feg=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.3_1575730927950_0.1548869435289102"},"_hasShrinkwrap":false},"5.0.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.4","nornj-react":"^5.0.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"4595876177f2d19ce760e74946dbdd463504290b","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.4","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-5JYfFnrdatnukb+Q3JOEuOBxmyPHC6mfVipqJJXpvwxZ6wub6qdCuLcZcZriz4RGWvoxHvfHPhuj8UnSqXqT4g==","shasum":"55f73692815aa119d1828566da8e6b9b1b90a9ab","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.4.tgz","fileCount":12,"unpackedSize":56546,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd7fNiCRA9TVsSAnZWagAAzrEQAJQwkTZUGtEO9dsm9ooD\nybxY7Q62JaIZoma2PKDbNFJ+9b/nIka7qQ8+Wbf/ptHuZeaFNwXuXDOgKa/E\ndXHJMdiWkOQMepXP1rc3tXgl/n7quIdgmk7e9hPnMw/qIHE1YITvJOCp5W1H\nYLuSDMVPJUGCcxN0/PbMSibD/J+CEMZuybt5AdoRrRliQR/NYUGSZr/J9cUq\nEaP8EZQbhzCeciZMSAU9mMxN42NPl2XVS95NYdocCyO7mD/m9lzy/ko62Wlx\nmhz/f3YiYX0/ItutHGs1LSftPSDIHodzQcPGSbrNnYz0B1W6ZJyEO1IAemA6\n5xVfdY80WgAB4/RRKV5/29YPxxJMPAnIl/pWpFsqiK/DFFIojym3IcOfTbvH\nhlVo/oO+SOgCA9Tpm+HsHWMn/vX1lPkjBwF0lRxCkKCdTJVD7kLxMhDMLPWN\nUdV93w71oBof+iVMjLcVmwg4AlW/ZQweEchCi5IeA8g/da2ETsqW9bZFnI7v\nCUlPKXdlz9bJsVGI4X3vRGPPzo3z9jlfa+JJpn8/Kxhisr3uoN9BoRoNMnCM\nVxKsqmlGNH0O0mnXL4u4N135RxnVDMDBMQQGQPrnnlU5oiUBO4Jc9apX4QQC\nxWq1Fcn51W9EctlCsQDzz7r0H7eeveeOiLg2EJ2D8ANdAXkc6X34CcfxaVR2\nb8K1\r\n=T/LN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAvrlUqFVcM6kIFhPUALWcj79u9fQy2q3oxZpohRNWlpAiBIiUop8BfAKFTUqT7g1OjWW6FZOPZid+BzyoBwyj34AQ=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.4_1575875426338_0.19420118461068325"},"_hasShrinkwrap":false},"5.0.5":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.5","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.5","nornj-react":"^5.0.5"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"d831f95bfa95fe19160b9c051b2d6c84f5fc4535","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.5","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-G5ZXwVF9crgExvL8raJb36ze0eG0m7Th/vpIf1ROJDHtfCTEmTKTXD8ka50JrD7yHUYhTD1RBIpyd8V27/k52w==","shasum":"8ad32aabb0f044a7efe5d481cf622380419434ec","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.5.tgz","fileCount":12,"unpackedSize":56546,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd7kVrCRA9TVsSAnZWagAAWugP/ipQG4BVTPdxtHX79bNO\ncQTtXQkPz7lpeFJu8LDs9ny5MVZlojCWbfNhngZx0FJ2xZr0jSj1DwmuEYjU\n196ciJXy7ygi3djlLQhySDHgKQ9k5omm8scefwLJ5x0nerhJuOpIpNtyoaAV\nV9og88VQR0qUq3Zaf6XLsO3CGR9hnxA2x7qKsBvtISdUxqvEztXmHpclWzYT\nUiBpi9C2g79A8VB4ZjEyRMfiLYGmTMqTW+rvhjGT9oC4mZDhy+k4ZJQLDK7i\nGgdDR25wTt7xhO4nO2ZoD00s/zHu2vGqpwAGLGWI28KP4bcXX8irrJAwiTJa\nP8LPl8wyZLjxBfbrsgH0iQTLXqQxH8zG1a7UpfoDk6nG3KcEr2UYRLN4G7oZ\nFXJFiSaBSTmDtcEduuq1VtC7/31uBW8DEEfbgikz1xYGecUXBqW7uYA3nckF\neASvDgZiKYnoHwhT2AYwMrSEO18w+LrTZitBwVLg42hpBL3pOs11Y9zh6Y9/\ny+M6jEFSF4OpEJ7GYdYgpL3s0GghKgGfQZ92AV9a8xKHOP3kdYZOZrk4GWGj\nXI10vwjmZagD7O+EI58hKdJv1FI6S3j7rh8RLLWoWweqaIvj+HiUedtw9OLZ\nIlb2vts0DYJ0FFK5S6vGuCUvEx5Eo9S51zO6zVkmuQraUk2+v3xDusMoEheT\n4cuV\r\n=gMTh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAudJJ8CzXP7+N10z706Eww7iNjc83H0NJpszbDlaKCNAiBOks4sqG9/9xNhuMm98JGmx67Pe8PnI64UaYeznhoSJw=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.5_1575896426761_0.1597056537474566"},"_hasShrinkwrap":false},"5.0.6":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.6","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.6","nornj-react":"^5.0.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"a031fc3dfcc7dd856ae4d9f388486d132146b91a","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.6","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-me3O/yvODUFdpg5h6/UhE/YhWOmT02eFxInF7vNN7/YIQAGUK4Spnh/acJwGADvcRvPPZvYf+DMSA5jTrQ6h3w==","shasum":"9dc3570920e5c95c0edd890deb464ff929137a58","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.6.tgz","fileCount":12,"unpackedSize":56586,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd+LeTCRA9TVsSAnZWagAAVd0P/15G0Ws1lBEk+A5OVHf9\n3u18kv7hX+loy+L7XFFaC1Zbavaj3BitaPEXvy3zGUP2N/cfbrB9gu7DLhHf\nO25lAC4VkEhES1cr1t926EL59dSeYMBo+pLbbj6SyiIyfWukX1UDeMTtFMoV\nqbju8Oafyy3oBwq1lJk3ymr2MmgAxbT3NyIodcfwVI2DWjs5B2bm/QSFqxP6\nAxfu4PIiAiSFLwSgTzzAAKEUUWLqV+Q/wAI45TrSKlSYQu5pGf7zyUMJXJHg\nMRgd+9GZ8rVR7slzsvx+T5qXH00UWFw6/P+sNm5b4wYjmtF+0yRupqU19uXv\nrXIB9DEdbatmIG78geV65MAVpjwLYHWfS3BSebSF6wN7hAClTiQHsN/vCkCL\nxIX8+YQVetIBnpsR88VcsdiqU78yMEiZcVQ8BuViMFuq01QCTglFn4Re7xTI\nU5PjrcfztyEcEufhvyCe/J/ibBy5isA5z5h5eW/t/VdEkuSTMLoe7Apz7PIb\nfGHRhp7WQMxvOv3fMX8M8vc3hXlVT1Jq0aSdhBWgp9NHLwmecVkm+Vhq1tLf\n//uvWxTDnF1tPatTM7KOtZIpoxhy2KnzJtObCghiqG3lkzipEELgCDIlurx7\nJCMnsHb8lHUphGB4V3ut4XmNMVAubbUeobW6WWlcnnU9bowY7K/vhNUyFJGZ\njP3Z\r\n=rYfw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYHyeOR3G/KQwi9v+6Pr4iJqZ8dz5bDbHLRecSIWCiFwIgJkck2R6Qc+aI7JUPDqQ/mNDl5ZiD/v29bGZcVEQOegg="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.6_1576581011219_0.5889741484331796"},"_hasShrinkwrap":false},"5.0.7":{"name":"babel-plugin-nornj-in-jsx","version":"5.0.7","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.0.7","nornj-react":"^5.0.7"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"9580e6e8bc9620d8e08923cd05226d44d3cc577f","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.0.7","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-Tdf7kqzViH/KYED2UOdgMr7OkN2of3pUItwTAA/jrofQj7zVwoh3HV6Bw9lT5tV8HaXj7AT6HvB9NWEsAFa8YA==","shasum":"ceae085bd815ea9d444a2c2287d8aaaced2fbe1d","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.0.7.tgz","fileCount":12,"unpackedSize":56547,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeCyJuCRA9TVsSAnZWagAAakoP/0mNzzqNFWF4TpQHLizc\nYHQbM1GpZ6ugbUMLAUeDmbCXQgST71ucw15vn2fHeqBesLc0UQb5lL5DSy1v\nDHSQbgVruoQgCA+mTIRcX3ZF3LhqyRavlWX6x4wSE9PkXTlYdZe2wkjwIa/1\n1kWWCOPSClH3jKuw3IofAPCGj4PMWmxeWYbCmtXBYyj5lNPT+Vz/EZa+jEpN\npjnyXYgP0r1NaOnFmRG0AEm58gD6oRzwQTOHgb1VgTGHrctPtJG4l6uY2jKe\n6bcHU8xrkQ/VNJHEPEOqfCiVHTnAnZQIwkFUc1zikUx1j15BplGCA63Wb9Cp\nxNasPqXP5+rxOEqqhNlwIsXUSe4mX/3+rR4ID2eg2nZIkk9m0J7M8QRx7T1s\nf3u/Ce9zuCAJrFE3pfofJeFMzIh7Wc78XboMZQkqEFwJfVTQRqofqAV842Qa\nbWEYnq5xMOD/DEkAa9pyjQe+18YbmaHA44CFaPs36XnmJlWZd2/NiVpwu4/i\nSKCblYF/nDfYLziKzuAe1xJT3smQ+lEij9rSjMAwfOWJa4GciqP89n77anQr\nhx9DPO3p0qs6eupLq5AMnslySdfEvQg71huh928FueE4DyFznlsvgFqa3BmL\nYyf09U4h5vtfKw2x9fy2fGMzcFMYy4NGL7Oxm45AAACA9KqmUCzDiOYTrmt1\naw4t\r\n=rDbe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFFpKFGiskTx12SBEs1ZvN/s5m3+lmUHCitv/hCCZ8ndAiAUC4gIQkmfAc/VE+yaeuiXgt1jwIsajknmMuKqQa+q1w=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.0.7_1577788013617_0.6672592018895003"},"_hasShrinkwrap":false},"5.1.0":{"name":"babel-plugin-nornj-in-jsx","version":"5.1.0","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.1.0","nornj-react":"^5.1.0"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"bfa12d1021cfe73c29f8c0f8b75701faff653e6c","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.1.0","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-uxiiGJzEIpw1l2KDazaSm0luOfs5QDvH3VMNGPNjjIEnJGbTjgWjUjyYJ/6cPYV/qWZ/Xum13KMr7c09j2O+Hw==","shasum":"87f107d61563a3aa4faaedf5100b8ffa8e7731d2","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.1.0.tgz","fileCount":12,"unpackedSize":57482,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeGFk/CRA9TVsSAnZWagAAtJ8P/27DRGfuvuLHg2GEWjLS\nGQQDoq0r6rwAZNQpX0EjNhKsZoRZCusrURxp5emsg5fIqL+7UykDS9yht4j4\nrXiPXoVfVRDcUgRYGeWHZGlMtVp2Cc7ayj7XwHmICoMArqmoiJ+Vq08EtHlB\n9JjkIJkLHbFXqTuZIbY4N29fWMBBSelYlFpUBqKLBjT2/q7v2b9bR4WB+rZU\nQofQqv9AxU+JF49GWva2xqANuasrvPK56oaWHbAYW6dnn8W52owz2w5M4+0n\nPkcJc0WpBZI6U5tHCnRIFxw9Ij8YO+vwgTfDBb4QDwHPr6q80a5lQTvU83qL\n6gKhWErMUv2D/5VrEZzzojdQCynFlAe3SqNe608HlZLllRcKMTSCwsuWoWi4\nYHK9oysicJ6sKMitkw3XElTn4ppvyrD6bqX1H3cb+kGqvv/07yKh6dIQHjsC\n2My5wu1geyg5/mp/oiXRTTW3as2AnyzTsn4/e1BinT8QGjTtG//hWQRrwW8/\n63yCqsjPiZvlixMTwXjl3/wyW+XOexruSw2wMERWBgU5rx6gAJP29glnsdgn\nILPJO8oYd5+1zLrqPhX8CVX66nlHWUaqBErQjbZlbzffxE8AClgtKVXviXsm\nCbJk9spzHcIR1ws903J9ug5O87R676TCq1dozV5KtvZKV6kO/qMAALKEqlqb\nzQMq\r\n=EbRb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDKfEdTLUxpiOnYMceWQ8wuCkgn9/itWF+lUWCLAM9yBAiAEC9JPIy2OdBOftfsEJQB+E0CQGJZuuur/BiYhpWU/kg=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.1.0_1578654014589_0.6998097159113608"},"_hasShrinkwrap":false},"5.1.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.1.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.1.1","nornj-react":"^5.1.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"a361cb95ca630fb0bb49711a83815bf29d9216b6","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.1.1","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-g89AzZTCbs78JBYuXPwb2hljO1xr50tLWo/JuLPtv4fVC12K/oWbx6QeVjyFDml4Oals8xhDrReFVDJ/UIPqOA==","shasum":"67866159d10f4078dd160eab5e211bf4c8515fd1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.1.1.tgz","fileCount":12,"unpackedSize":57482,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeOp2HCRA9TVsSAnZWagAAarsP/AmEhy/Qh0pQKXBNP0Bu\n9G6N3FMQifehklF5Yt3hzKVkSZH4tRYQlWA7vsQNuBcDaDRg3fqSeiRStqai\nDDZ+/z4g4QzqKhtK9BFZGobGD1KzwQ3LALoffuPpC9UZGGoStBt80+zL+KkW\n+/LSVa5Bem95oGm5B1dU4jO6wvTZkrXeuovJHGahSEHmOBUqDMQSCRfp7W3R\nnxdYsZ7K54F8lUzcbRuuL9HDVsQXvHoOCr7VSXiqaeb8sKgKGgZfOh3i4o87\nLNSHLQ2fRhjrUg/UV1N9J/MiQng0OSpLk/lr2+jlFb2c6ufUdT9dvoxJEc70\n+OUwKuSPwyquYAlEeL8LsYS0ZwZkKmNal1f7BvNemtRgsZqqgc5x4gz3R83x\nDQS4bzx4XING2dB0G3GmYJ1haJ7KnbgWIf6mCzkS2yaph5A4/VCPkhRE/EZy\njXEHFJlzd0vazgDbw6qKq/F1oshgBl0j01t1m6gP9M1X+n3BC6dw/xEdLKRC\nivtjq3QalV+0cuRqBkRPE4a8+pGoQ/OAOcrAf+58X2WlSP1W7xLcnpgtRes0\nNyNRIX32F0yCKlucrPVfgPehSI6IGR/0e2JqYBuDh9NTJ7yGuLYX/R7C+iig\nf84ER6ieRp6702eTNUS/zzVzo+HOtiKn5OxcSWEwwwHOo2hNit0AclPPTbkL\n36SR\r\n=HnIr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAhhse0N1NTRICpiHTbh9qwO2N44sV5DtQ88ASYY6tMUAiBb72Yed61Qp2stxIb2zVY+5lm8GaNMshd+SEuNsu98sQ=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.1.1_1580899718875_0.0036045579186885224"},"_hasShrinkwrap":false},"5.2.0-beta.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-beta.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-beta.1","nornj-react":"^5.2.0-beta.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"e62c190de57dc87b8c0c0f266cc37f985ab8738e","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-beta.1","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-AIxpzai2ackVF+KJVm8+krBCz3oerff5ym7rbPV+4j68eMSPqG0g7AnyS/hbyd3ksddzJ27d7NKHcqo3FKVZ9A==","shasum":"b64ccf339997d6092bbf9c15ec29139d004a4ea4","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-beta.1.tgz","fileCount":12,"unpackedSize":59790,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeclyeCRA9TVsSAnZWagAAlW0P/3SvoL7RbjqLJghAYcWu\nog6IaogajgQ0lbFt7y9p2+cg/3J8OZk0DZHITorw8JiUZvy0KneQKKoy3QE7\nHgaKJ9qIMlHDLJ/5dUoVQxBRF4PHvA2/YzZRnD3ruoMhU0IuS5n2r6Ttz+yV\nsDesxGXLfUAr5tQ9UXjYbv2iE7zWSm+UPM6L2Fgpgn1XpbMyFg8sfZM6rQdb\n9+enYEh/Urpo8JDzHKJIwXclTfjbH8/Z/Hn2ZVGrLge4dpdPeyyyJyprmuVf\nF436riZAHZuyBcYdvDApuOHU2LB+XLpPkJC8IeCjX8yebjN5R2Fh/XQrf4nM\nmiqT/ibPTh7ew3dLYcM4PlLI0maF9zyCXqVef7nWq+MUlwvcdza23Fh6Au55\nMB+FEieiUpj2IFjBbyq+oa7kiLQ5oh386+cnqx5Wx55omO9zGeMyxq44JQV4\n1Tvv3mafkcyr16OX0t+7uJN6gg2HLHKzcgDDZqXCm5RMQ/fHliV+ploxVgpW\n2T1advI/xHiIU2fiHlYgtV+yry5IrasW6ftzveCU6JwReWEBQl/QfsEcDgsB\nZBalYy+bNqFWsmdENqhsAvP7OwsOOQ6SrZKpuRgOGY0waWJn9uSyA+AmC+L5\nCTCYgAN7mIkVitMt9GFz5iHXOH8N3U/gY6lV7du28XIELqsfU1cJjEc6tFyF\nejo1\r\n=bocQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCBGGZb54NN5DEQG4JFCigLAmerOCfTwIrp9mx2TYhc4wIgK4sLHRE0EzUkuNhziYI4YfMBpTKGrW7IxQUiWREHqMQ="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-beta.1_1584553117717_0.3421021712110386"},"_hasShrinkwrap":false},"5.2.0-beta.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-beta.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-beta.2","nornj-react":"^5.2.0-beta.2"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"6448693e185e9f5fca4a06f1220f6c33d3d460b0","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-beta.2","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-tszxzuTsEGI8EFradPMtVDtQEu4PNwYKK/pUadEvIMj0NF6r4b8bITFOLAgYsUwNZYZ8SrBuNpC4rQj8eozx2g==","shasum":"a95bc0d845ab6e97151180a2c1a1b6f765bdcdd3","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-beta.2.tgz","fileCount":12,"unpackedSize":59790,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJed4pxCRA9TVsSAnZWagAA8gAP/3ltcrxt6FcrGNfrDRxe\nxISvYlyOG6EqrppGFLTa0G8LDHZBXvhjvl4x56PQAqg3f9mFw9sZU9/JvGMa\nLbzx7RSesHmxHNMqEVzw+FEQfzD8teJmJYtIJA8mLQM3PGo4/MgSAAek+zwr\ndI5/EXHc/nsplbQZiYkvUtPIUTOej3EdVw9EpZJ9o7c4CviyymFeBnF2tRfc\n28QmbE6f6PfIjU0sEDrsfZhsdsH5Rq4uRfFzCb0jGz90gn8OYmeX0PPG3S8Y\n9ozdGTFsnAn4LYDzTOT6ZsuXhLYmnBVnv8DvxgLa1Qzq5bWrlz9vaR2b+YmS\nBGLMZnOLh8PyboUQXVwdpYm/M/b8BXXi2HKZZpVDkJkAfGPALs02m3BlOalQ\nw1fgj1K6eQO7RQZ4wc7SbWhcHroPfNUqbjaoKgK9Lx9WFM6GrHZET8S22WbH\nGZZLN34tiKdRJQdCpUMFP2XkWzGtiBL60iExt4vkcw2mDWo7TDxIgKGDTI1Q\nbXvcoEhpMFAhI9jJJJ3/p9Tcld86uNOmzbTqSzIUOoFvvccCdhMO8vhU0zfY\njZeTsqwTcQ3S76NdbCwX7u4/N1cWQszpWjq/iCaZNTspbF/Mf4UVW8LvBl9X\n44kJh4WoCKl+CfKx4QmUEKmLhYypUu1N+EB9fZcuEhx0jSUyID8aprarjQ/7\nJn2u\r\n=wJDw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAsNW3heDubnmmku028wNFiiIJO9si90NCZlrZSsiEswAiEAvOPvwLzQ9/QYH0ERVoIKG/fyJKaLALPLQcqwL+pn4ao="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-beta.2_1584892529005_0.07347931475780656"},"_hasShrinkwrap":false},"5.2.0-beta.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-beta.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-beta.3","nornj-react":"^5.2.0-beta.3"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"4d019414f59bc06860570e9b1d1559569622f56e","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-beta.3","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-2URlHG8/6Vf2/tRbt0IGF5qVIMyrFSJhHClf4DHPJePQW1i6WXbO0Ac7GVLwmSGVDZZj+3i6yGLa7lWeR5QNdw==","shasum":"2352d523099cfa97286bd3e694928cd862ae6b87","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-beta.3.tgz","fileCount":12,"unpackedSize":59790,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJehyMrCRA9TVsSAnZWagAAa50P/0oJ8fJgUndiHyGmgtDu\n6gKVfVtPMOIUre0Tn3+KAFPklKFBR/DRlmJQuqjlD6bdqGrGhCTSDaML0CD7\nfHdTQuhs0jGsmzql9tBJAFhi2EXd0i+137d8rywsn4NHfqXSmCNMsaDMQxtb\ngioydmIpVIKmmO8KbXC0HyaHapTG6QGjzRpwnV7T15dS01q+0lDVHMs9VCrE\nm0g5mrsx178/2LN6TUoWjXrFVYADGrjoiPXCMc846rNxr9NKk8Ae1TDRmq08\nmb2EA028h3R7SpB4GX4KqZWmg0gelcAh3CkT8HJ+kSQ3UGZCCm2y0bPcVJNZ\nbnhpXI9LjHYLAVCSLzdzhidImkUx/zw7x4SW6HdawmE57psBGlXtB1E3Itb2\nlWccVrg86wHA8LMw3gy1NN4Yl78AizjE8AO5e1vvcWUf28udkyk0ypey0iQT\n/pj5MxNYJuiwtEsNKiLWq1QCCP4CIalP7qbGPEiniSLuveqItIrb/MwkHfJ1\nXI/Fc0KIQdnBd6QIAVzrNhCrzoBai2Phxr/v1OPaabgZuN6C6IUEElwmchc3\npBCoLxn1ob9b1eZkfPdDCNBcoaqIiMDi9zIESFMclgeBJiv62WYYyDxxgytG\n0rjXK4NdjRnouVzBba1scMj6jbdh4qmPkTejJj5vHcjUm+vGceLyZt8rVBkN\nZVaT\r\n=NmLa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqLFQwt1PWx7zclQw9BppYXi+sqpsKXJGSDP8p6nFLAgIhAIqN+Alh40qZa0vdUyzBMlsmxJMqtQtmiYtoqzfimP2s"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-beta.3_1585914667541_0.19214305689975086"},"_hasShrinkwrap":false},"5.2.0-beta.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-beta.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-beta.4","nornj-react":"^5.2.0-beta.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"876795738140b9e01c65d9db8e10842942b9c776","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-beta.4","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-m+oLjuDwzLWNLREPtn+tt5EprUichPRvwIPQ4cEZZcLGiB1fwIohEHEBZK0bdlPQG8G/ivbwQ1q4EDBHMT+AKg==","shasum":"0d892fad29aecd86f6cce482e85c8da2349901f2","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-beta.4.tgz","fileCount":12,"unpackedSize":59790,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJekGrpCRA9TVsSAnZWagAAltIP/AksaiTp0WZ7nTleYulM\nJYiuDgZJi6P4FO4hCEcL3vAB697Q6Q03rRsZmJdmfCnyHGT5SdGzNL703kKO\nvrFklD2XCTLG16kmcHNK2F44WptaUUpogIk2lrIju+4K6x2HrudNDSV1vip9\nZAj1+4WLyteKK8BoM8Fa25jnc/xH+9FTJUW8MSlH/SdnFfVQE2/PbFjQKUJ1\nHT+XwIuz+kQRRCC3yf/lcZfVJIFdOoy0VCiyTPSr8SU2mZQRTJNuXNb8MBBe\nM9ujtOvwS80xH6tgWocyjX0+cOiVD10tx7CkFHOX32ZzrUacKog0UJtyAYL4\nKCxUUJfvK4D4quj6vw0rU0CDAK92+UWdFKKt+otll7r6iSR0rxuj2LhgaqoV\ngPEwZpHjrpjcZW+tuzWDhKLVSNxsWzMqRn4gxvLKWO1LQznn2p8GVdz4FySH\nNvr83xtSrjvBlSa3DAQ434Mzf7pnWoechhQx8WksyHe+qOEx5go/SlDLTTBB\nH0Vj6qOdG7HOTJl5c77s4R1OjYj7Gr2ttPcOSRXeVPl9+GvIthjPfOGf7Ist\nmdIQfVmbCFNI4g9OjUjRMqNvlo40dPhhlJPunB9pVjieioQjFkSQGraTHtmv\nNSf5rMydIUG5vz4KooURQ3TyXMQzwbz3ii3cRmZib6VuFQLBoG7u9yd9AODB\nXdi8\r\n=hqVy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcrlv0JCY4nZSlm6FHFPhPPShkTuDm/yCJrkXEIvaqnAIhAL3XeEJ2vja1c2McOsaP++UhNF0V4D67vBfBa0mZNwPx"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-beta.4_1586522856824_0.5143089668012084"},"_hasShrinkwrap":false},"5.2.0-beta.5":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-beta.5","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-beta.5","nornj-react":"^5.2.0-beta.5"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"eaea9d36f22be345306802a99628647496139875","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-beta.5","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-uAfPMGXrXXzAqoxM7sGaAEjSLL0gKIZtMvEKisQ2eflsqHbbHmOIUTv2uxYEMzbOR01ZfgbRUKbbZIOdjVzGsQ==","shasum":"26d42619ee24a13404e3948da92593ecec98f9f5","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-beta.5.tgz","fileCount":12,"unpackedSize":59882,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJekyBPCRA9TVsSAnZWagAATeUP/AjFYHMYrQI7Vi+x0qF5\nV0GoI6Ous4yJmc05bUQMVb6/cN/nwPKQP3NkMuk4log01KdIX7YjBWpvsfyV\nkMHpNLQWvJDLhf2usJC+MGDpCuEswqIKXh7YJR60A5gQ+aJAAHC4H3fuu+PM\nMtRQJZhXemVpmD9guzNqcm1FTryQGgXz0r6mHdbKUcEMFL0ioyZM/O+23GTg\neXWhd9+RJCXrCcpAZ9YHZQvVcHMHYM7sSO8e5RZPc3Ly0cZWbGtULpBAI5aY\n+2Em0d7qwwrhUifm+IfQss2BDTMNui6i3b+XjlDKPVcxB7S2CHsRB5BE5vg7\nIVbV++2aFEnLpV1DG+yRjnfZH+zV5wJHvwtyKQj6sfW5Sj7AHQ6zqq9Y0JNF\nH7B5QxQA2JTHcsz6JMsMmc0sNbdlIKfn7aY2j1043B4q+pqxDYoPeoD/PNbq\nrrp4YW+hhA7sQxKmpZwBaO5wcBAnQkAFQPDvMmztfo0GxAc3YWiuPNszr62o\nup0U4JFLFwEd6spqIY33IXt3mvSe35ep5A1aGG2nHNXmQfO+hQV0FI62/O+v\nKTZMGoHZvci0tIlHb+uplmnLYP+Qtd5lmaWi+2Hs95gnfs2gOv+ckolHb25Z\nTUyY2mBvNgrwr8SSHf5Sp9aFYBXPf5YXNFxWRi8toYOxeFWNxrCf2QzIVlSW\nLMwa\r\n=MKuj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDmknWZFDNILG79KaOX1owtNwDE9VFHB9b3LsTJ2aoyrAiEAnY0XS5hG5dTn8xOhf+UIEEwG6avIESLAEKr4D6PfwDY="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-beta.5_1586700366462_0.6748310437720013"},"_hasShrinkwrap":false},"5.2.0-rc.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.1","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.1","nornj-react":"^5.2.0-rc.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"60647d6989b3e19afa752c123e49c0b8f5cc25a6","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.1","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-LwI5/vjHcc22kSjy5AvhtkKt4y1wXwfNfVM+QoyH436O5ow881J83/vaXo/n7DYsECsg+iH26mHpwv9keqw3fQ==","shasum":"5baf00b2b77f5eee6358b14f94944e538f6a0f41","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.1.tgz","fileCount":12,"unpackedSize":59931,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezep7CRA9TVsSAnZWagAAW+AP/2yOFX9ZMtgb0uchmWXU\nUZwhIw2ZlWN/NSMS1FK7NSKboiwuoaAP1JyvE6kVzK0Gi+pwxin7ZmoAPkHT\n8GGpn4kJzmeaOFESs1lLO5OvyiUXBuHe/T0pSrF4o/UZlm77g8YBFoZh5GtS\n3wG3xSL9EiPYVD+1IVZ9LMoJgxv38hQDenJVv3RADvOM5Hz8krtQPDOpXJ0X\ntLUWCa1+FFjcj8SI46Fu3r51TnYBikZIsHEdR300YCsIrzBku/5A+XWO07KN\ndQZ3o/Z2GDjTMuIwIfSh1U5VfBs2tkoaEkYo7bjA22HG7e4ECRf9+rEBOGM0\nwFQbe0QrUNE28/zkLOHZ6lzF05yGeoaj7IPfeuhqCukusHdGvbkEdcA6HVI+\nOZSv9bucV8Kguy1oNnBP6J+Ix9qJI/O5cxHJkRFkqPs+gHaFQDaGaJsMgPKD\nVzPQG9dE7Fov1YmUPbbjwPCKgG2LYZP+x/3ZS6ub3eDzBAwlPK0blIjEubsJ\nRkTq1bntClvAvuxiXCg52JHv5uQ5XCSj8fjn/7V9R+5stWVm3UCkhaIOJxEC\nKY+M/GtuoqEC3qbS4ANk0ETHUuEOqsWVuACZcnFpAyv0gfp57cldYSsUn1w0\n0FW3FH7cI3tMEvzbyb7gPwBq/ax0v2aA/Cp1AHzYB/rrlOTjLJAopQCzbVwV\nFHYm\r\n=srM4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDB6wxw1NNhGOrOVJYelyTP/aVuSbJEUCwHV/FjleGX0wIhAKHPYwXlDdklwFEWCIAjze+Z5jJyUdqJnExkzVS+M/0H"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.1_1590553210879_0.2020313212018563"},"_hasShrinkwrap":false},"5.2.0-rc.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.2","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.2","nornj-react":"^5.2.0-rc.2"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"95ed4da4e13466132ba4b5897d7a0dffeb615a07","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.2","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-4PuVIrtUR1MFd3lZMTbE12k9+mqhLn5r5EVxH2qauUpNJqzREa5Eg+U+u4sq/gEKc3AjAowHnwrwhnS4ygI/7Q==","shasum":"012cd02da3d6c9cf8e1b9fa1d399437348b48f81","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.2.tgz","fileCount":12,"unpackedSize":59990,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1L4jCRA9TVsSAnZWagAAvvsP/RPSUhipikh1ovDGtk6a\nhC3T4KVaWPLYtZng2dJsSsT0uOv8atoiGIhov7SJb6sBY97htT8mkhTkNe29\nKHlKPMtW2Jw0/YSCfCsek9hHI/kzngiS5ZEqbgVQvjlYQyt/05cCcIiX1+WB\n7uEWryVrYDTm//JanYsMdwiHfYvCtfkkISNiZafj78jyeWceXl14Q68USGXG\n/BSFe3U7dSatHW+h3jUg5JaWcV2Dot0OwX282Se6UfRsfLmyQGBWmwmpKtQa\nChaFNlmhBVFC68Ya7Iy7erNT+oUyZbqVhUNsHS8H1fc1y6y5a6fPWUuA1nwl\n9MsFmWYKQE1FTk9AGxOngyhwYRClUuJ9LwxBwYj4F2Kkd9PZmXr/V9xVfqrx\n8ufWYjl/7+0bnaXPx6bQcNZFPI/s8UssLtkyhW8T7lxsU+l8S/hsJqqNZtnf\nRPUkzVrR1sLm+7BXlcWvnuQ5R3IuCW0bvPnLflPCJScLu/gCKbfnbUxh2ztU\n6zXoVRdUTNkyll4mUoMm1GPBmL2ykgefcdIiV5WSZ5KrLJFwn6D3LGS7uCnY\nur6JozWDjMo/3iOW3K3W8hfUst4Bwq20idBFHFmrodB1BlYXC0MlvpjeC90L\nOgIogioYBR8RPnvEIlDr+2ElEu5takA1o9wXHWSWRSmlVkLcEjo0vyV6xdYw\n0PPS\r\n=20eO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHTtWaCuhQRQ1MyH5/x1V7wgExTyr1IiU0tpm3h470gUAiEAo9BYJhHBwSkiln1xmL0FttyGJjqrEGrChs3GRn2SARk="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.2_1591000610744_0.8428956312632434"},"_hasShrinkwrap":false},"5.2.0-rc.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.3","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.3","nornj-react":"^5.2.0-rc.3"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"0a65360277e5389abf9b62e43315a77eed56de86","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.3","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-OVcwR1ufP6nRwV3w3NZHXqjJN6lrKl8N82A2crdPj6lHWw8Reue7bYDlhmwVnf4O8HmWyPVEarY2p0Udp1Of+Q==","shasum":"7493a1f8e81c859122ffd77b994c2e2647821931","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.3.tgz","fileCount":12,"unpackedSize":59990,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1MoWCRA9TVsSAnZWagAA0b4P/Au292CLcKIpTbUWjyaf\nUD0z9EilTNGAjqcrKp0D7Wb8gDrXaseJGlscWwODqdjCBJ36c5ZhPFv7TbbS\nvtDmkmppy0Wc395xQEqGN53NNGlmriwMpTuT0/oSmYmgRAHH2HzEcaeV//+/\n2YdB4nVUS0fhyj7W6tKjtm9ONvnX2P4xLtLzP9GX9FatY0pbmJZDw8fyxr2p\n1yOAgANuYs12N24dKkMLnxz8XUi+V6dwL1OVhgAENxd5+G11iQZ6gGH4Q3Ho\noyRLhjEDGOefijBDJIU8xwSoPy6Qk5FbdVvfrW860cOvZuJyBQ+FAfYpeBub\nK67PkQVoc9hZUPUaZiPMQ2y1JRWZw+XKrwXhxg/2damyS9d3cg2b/7Lea4Io\nJpCY+Ek8U7DvXmRujHDy2W8PwwDz7vbFpAfx5mHHgM7kR8rz1yCnTuLWO1Y9\nLaYjfXjCVPKQr9Ll2rOZepLmtdEOgnhh8itJDdS0za4FAPdrJ/O1459aTai9\nDvB5/9xm098n1O7JBe9KfeCqMgmqLUI+eVx1tWEoW6YJBKEOhsKLy4PxKx1A\nea1nxdQgFcE1Yu2rsfrGUDXGNaVkZDCeGZ6t3/QV6ZXqGl7tc/hufbvc7Gro\nPkVF/UeZFCZmd6EYgYK0SSpT2e1ntMBbqXhWyG00dzyUSbE1f0XkDOXuesVe\n3NLY\r\n=7x7Y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHXVtAvBxG7bIBp95sF0CCl3A7rKNu6k4fOHAC0r2g6gAiEAopfeYqCZFAU2AX/2/ZdLeZHOUJ6oP8ARTFhlLbCCJ0Q="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.3_1591003670146_0.6326534984994681"},"_hasShrinkwrap":false},"5.2.0-rc.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.4","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.4","nornj-react":"^5.2.0-rc.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"3737ad4b2a4ee09f43dac50814ee512a5404d691","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为JSX带来更多丰富语法的Babel插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n以及类似Vue、Angular的指令：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      {n`${props.name} | upperFirst`}\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像Vue、Angular那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = (props) => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-class={{\r\n        className1: true,\r\n        className2: props.hasClassName2\r\n      }} />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## 目录\r\n\r\n* [安装](安装)\r\n* [它是如何工作的](#它是如何工作的)\r\n* [标签](#标签)\r\n  * [If](#if)\r\n  * [Each (For)](#each)\r\n  * [Switch](#switch)\r\n  * [With](#with)\r\n  * [MobxObserver](#mobxObserver)\r\n  * [开发新的标签](#开发新的标签)\r\n* [指令](#指令)\r\n  * [n-show](#n-show)\r\n  * [n-style](#n-style)\r\n  * [n-debounce](#n-debounce)\r\n  * [n-mobxBind](#n-mobxBind)\r\n  * [n-mstBind](#n-mstBind)\r\n  * [开发新的指令](#开发新的指令)\r\n* [表达式](#表达式)\r\n  * [过滤器](#过滤器)\r\n    * [capitalize](#capitalize)\r\n    * [lowerFirst](#lowerFirst)\r\n    * [camelCase](#camelCase)\r\n    * [int](#int)\r\n    * [float](#float)\r\n    * [bool](#bool)\r\n    * [isObject](#isObject)\r\n    * [isNumber](#isNumber)\r\n    * [isString](#isString)\r\n    * [isArrayLike](#isArrayLike)\r\n    * [currency](#currency)\r\n    * [开发新的过滤器](#开发新的过滤器)\r\n  * [自定义运算符](#自定义运算符)\r\n    * [a.b\\[c\\] (安全访问器)](#安全访问器)\r\n    * [a .. b (范围运算符)](#范围运算符)\r\n    * [a ..< b (闭区间范围运算符)](#闭区间范围运算符)\r\n    * [a <=> b (飞船运算符)](#飞船运算符)\r\n    * [a ** b (乘方)](#乘方)\r\n    * [a %% b (向下取整)](#向下取整)\r\n    * [开发新的运算符](#开发新的运算符)\r\n\r\n## 安装\r\n\r\n```sh\r\nnpm i babel-plugin-nornj-in-jsx\r\n```\r\n\r\n`.babelrc`配置：\r\n\r\n```js\r\n{\r\n  \"plugins\": [\r\n    \"nornj-in-jsx\"\r\n  ]\r\n}\r\n```\r\n\r\n## 标签\r\n\r\n### if\r\n\r\n可在JSX中使用`NornJ`的`if、elseif、else`等标签。NornJ中的[if标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#if)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>ifBlock</i>\r\n          <else>\r\n            <i>elseBlock</i>\r\n          </else>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <if ${a.b == 1}>\r\n            ${<i>ifBlock</i>}\r\n            <else>\r\n              ${<i>elseBlock</i>}\r\n            </else>\r\n          </if>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n更复杂的例子：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1, c: 'abc' };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={`${a}.b.trim() == 1`}>\r\n          ddddd\r\n          <i>aaaaa</i>\r\n          <elseif condition={a.b == 2}>\r\n            <i>ffffff</i>\r\n            <div className=\"las2\">\r\n              <i>888888</i>\r\n            </div>\r\n          </elseif>\r\n          <elseif condition={`${a}.b == 2`}>\r\n            <i>gggggg</i>\r\n          </elseif>\r\n\r\n          <else>\r\n            ccccc\r\n            <if condition={!true}>\r\n              <i>bbbbb</i>\r\n              <elseif condition={`${a}.c.substr(${1}) == 'bc'`}>\r\n                <i>ffffff</i>\r\n              </elseif>\r\n              <else>\r\n                <i>eeeee</i>\r\n              </else>\r\n            </if>\r\n          </else>\r\n\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n/* 输出：\r\n<div>\r\n  ccccc<i>ffffff</i>\r\n</div>\r\n*/\r\n```\r\n\r\n在`condition`参数中可以使用模板字符串，并在其中可以使用`NornJ`模板中特有的[各种过滤器与表达式](https://joe-sky.github.io/nornj-guide/templateSyntax/filter.html)。如上例中的：\r\n\r\n```js\r\nconst a = { b: 1, c: 'abc' };\r\n...\r\n\r\n<if condition={`${a}.b.trim() == ${1}`}>\r\n...\r\n</if>\r\n```\r\n\r\n这里的`a.b.trim()`表达式，如直接使用js原生表达式，则会因为b变量没有trim方法而报错：\r\n\r\n```js\r\n<if condition={a.b.trim() == 1}>\r\n...\r\n</if>\r\n```\r\n\r\n但是使用`NornJ`的表达式则不会报错，而是会顺延流转到下面的`elseif`判断中，这是因为`NornJ`的链式取值语法对`null`值进行了过滤，[具体请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/variable.html)。\r\n\r\n### each\r\n\r\n可在JSX中使用`NornJ`的`each`标签。NornJ中的[each标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#each)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={[1, 2, 3]} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <each ${[1, 2, 3]}>\r\n            #${({ item: item, index: index }) => {\r\n              return [\r\n                <i key={0}>{item}</i>\r\n                <i key={1}>{index}</i>\r\n              ];\r\n            }}\r\n          </each>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，of参数为要遍历的数组，参数格式和上面if的condition是一样的。item、index参数都可以不写，默认值就是例子中的那几个。\r\n\r\n* of参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return (\r\n      <div>\r\n        <each of={`1 .. 3`} item=\"item\" index=\"index\">\r\n          <i>{item}</i>\r\n          <i>{index}</i>\r\n        </each>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### switch\r\n\r\n可在JSX中使用`NornJ`的`switch`标签。NornJ中的[switch标签文档请见这里](https://joe-sky.github.io/nornj-guide/templateSyntax/built-inExtensionTag.html#switch)。\r\n\r\n```js\r\n//转换前：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={a.b}>\r\n          <case value={1}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={2}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n//转换后：\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        {nj`\r\n          <switch {{${a.b}}}>\r\n            <case {{${1}}}>\r\n              ${<i>1</i>}\r\n            </case>\r\n            <case {{${2}}}>\r\n              ${<i>2</i>}\r\n            </case>\r\n            <default>\r\n              ${<i>3</i>}\r\n            </default>\r\n          </switch>\r\n        `()}\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，value参数的格式和上面if的condition是一样的。\r\n\r\n* value参数支持写模板字符串，并在其中使用`NornJ`的过滤器与表达式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <switch value={`${a}.b`}>\r\n          <case value={`${' 1 '}.trim()`}>\r\n            <i>1</i>\r\n          </case>\r\n          <case value={`'02'.substr(1) | int`}>\r\n            <i>2</i>\r\n          </case>\r\n          <default>\r\n            <i>3</i>\r\n          </default>\r\n        </switch>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n## 指令\r\n\r\n### n-show\r\n\r\n使用`n-show`可以在JSX中很方便地切换标签的`style.display`属性，当值为`false`时不显示，效果和`Vue`的`v-show`类似：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-show={this.props.show} />;\r\n  }\r\n}\r\n\r\nReactDOM.render(<TestComponent show={false} />);\r\n/*\r\n 渲染结果：<input style=\"display:none\" />\r\n*/\r\n```\r\n\r\n### n-style\r\n\r\n使用`n-style`可以在JSX中使用与html语法一致的css写法：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  render() {\r\n    //以下与<input style={{ marginLeft: '10px', padding: 0 }} />效果相同\r\n    return <input n-style=\"margin-left:10px;padding:0\" />;\r\n  }\r\n}\r\n```\r\n\r\n在`n-style`中也可以动态嵌入变量：\r\n\r\n```js\r\nconst cssProp = 'padding';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-style={`margin-left:${10};${cssProp}:0`} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-debounce\r\n\r\n使用`n-debounce`可以在JSX中为`input`等表单元素增加防抖效果，以减少用户输入频率而提高性能：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onChange = e => {\r\n    //每次输入后延迟一定毫秒才触发一次\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return (\r\n      <>\r\n        <input n-debounce onChange={this.onChange} defaultValue=\"test\" />\r\n        <input n-debounce={200} onChange={this.onChange} />\r\n      </>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-debounce`的触发事件默认为`onChange`。如果不写`n-debounce`的值，默认为`100毫秒`。\r\n\r\n* 指定任意事件\r\n\r\n`n-debounce`也可以支持`onChange`以外的其他事件。比如`onInput`，则需要在`n-debounce`后面添加`onInput`参数：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  onInput = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-debounce-onInput={200} onInput={this.onInput} />;\r\n  }\r\n}\r\n```\r\n\r\n### n-mobxBind\r\n\r\n类似于`Vue`的`v-model`指令，可以使用`n-mobxBind`配合`Mobx`在`<input>`及`<textarea>`等表单元素上创建`双向数据绑定`，它会根据控件类型自动选取正确的方法来更新元素。\r\n\r\n* 基本使用方法\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，无需编写`<input>`标签的`onChange`事件，`inputValue`变量已自动和`<input>`标签建立了`双向数据绑定`的关系。\r\n\r\n* 实质上，`n-mobxBind`的实现原理和`v-model`很类似，上述示例其实就是下面的语法糖形式：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  onChange = e => {\r\n    this.inputValue = e.target.value;\r\n  };\r\n\r\n  render() {\r\n    return <input value={this.inputValue} onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n* `onChange`事件\r\n\r\n由于`n-mobxBind`默认自动设置了组件的`onChange`事件，但有些情况下我们可能还是需要在`onChange`中做一些其他的操作：\r\n\r\n```js\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  onChange = e => {\r\n    console.log(e.target.value);\r\n  };\r\n\r\n  render() {\r\n    return <input n-mobxBind=\"inputValue\" onChange={this.onChange} />;\r\n  }\r\n}\r\n```\r\n\r\n如上所示，`onChange`事件的行为和标签原生的`onChange`完全相同，它会在文本框的值变化后执行。\r\n\r\n* 增加防抖效果\r\n\r\n可以使用`debounce`修饰符为`n-mobxBind`提供防抖效果：\r\n\r\n```js\r\nimport { Component } from 'react';\r\nimport { observable } from 'mobx';\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '';\r\n\r\n  render() {\r\n    return <input n-mobxBind-debounce$200=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n* 使用`action`更新变量\r\n\r\n在`mobx`开发中如果启动严格模式或者使用`mobx-state-tree`时，则须要使用`action`来更新变量。可按下面方式配置使用`action`：\r\n\r\n```js\r\nimport { observable, action, configure } from 'mobx';\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({ enforceActions: true });\r\n\r\nclass TestComponent extends Component {\r\n  @observable inputValue = '1';\r\n\r\n  @action.bound\r\n  setInputValue(v) {\r\n    this.inputValue = v;\r\n  }\r\n\r\n  render() {\r\n    return <input n-mobxBind-action=\"inputValue\" />;\r\n  }\r\n}\r\n```\r\n\r\n当有`action`参数时，`n-mobxBind`会默认执行camel命名法(`set + 变量名`)定义的`action`，上例中为`setInputValue`。\r\n\r\n### n-mstBind\r\n\r\n`n-mstBind`即为`n-mobxBind`的默认使用`action`来更新值的版本，用来配合`mobx-state-tree`的变量使用：\r\n\r\nstore：\r\n\r\n```js\r\nimport { types } from \"mobx-state-tree\";\r\n\r\nconst TestStore = types.model(\"TestStore\",\r\n  {  \r\n    inputValue: '1'\r\n  })\r\n  .actions(self => ({\r\n    setInputValue(v) {\r\n      self.inputValue = v;\r\n    }\r\n  }));\r\n```\r\n\r\ncomponent：\r\n\r\n```js\r\n@inject('rootStore')\r\n@observer\r\nclass TestComponent extends Component {\r\n  render() {\r\n    return <input n-mstBind=\"rootStore.testStore\" />;\r\n  }\r\n}\r\n```\r\n\r\n如上，`n-mstBind`会默认执行camel命名法(`set + 变量名`)定义的`action`来更新值，上例中为`setInputValue`。除此外`n-mstBind`的其他特性与上述的`n-mobxBind`完全相同。\r\n\r\n## 表达式\r\n\r\n使用`nj.expression`可以在JSX中以标签模板字符串的方式使用`NornJ`的过滤器和表达式：\r\n\r\n```js\r\nimport nj, { expression as n } from 'nornj';\r\n\r\nclass TestComponent extends Component {\r\n  render() {\r\n    const a = { b: 1 };\r\n\r\n    return (\r\n      <div>\r\n        <if condition={a.b == 1}>\r\n          <i>{n`(${a}.b | float).toFixed(2)`}</i>\r\n        </if>\r\n      </div>\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n<!-- `nj.expression`的文档请[查看这里](https://joe-sky.github.io/nornj-guide/templateSyntax/templateString.html#njexpression)。 -->\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.4","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-6//cFK7nfwOzE6oVUZwSg4+fm0GqfkYFOwAvFVS+/dzVltd8nzUDO+5/DWOm/Dl7mPEGv0WhBWswtoNSPnUhRw==","shasum":"5318642cc61d0d8356b7d0a646665424e3c3ca12","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.4.tgz","fileCount":12,"unpackedSize":59931,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3gAdCRA9TVsSAnZWagAAQacQAI/dHyQNwZHfyt8oV1j4\n1Ss7Y0cYs/ph3ONL4D/uSJ4q5Qjxnll62pLLIR8j7Bj1+0jD6PaETgCRByWd\nS7GhpB0GstZpWQC/8+Ge/KVlkZa1IqYtDFgVTIogxqAi0tg8hWBvw9M6Whj+\nFY11vyFpnPZ/LsLwGi9bOxnCnDnineA7Y9rkojEbvKscnybrG/ILh1tbzPd/\nl5ymZZArvZq2sQ6tJs3NVRiVJLYCmlcRPj+xrK2COdNScCE69SR/e/7ikwli\n1a6zPAVnk0Fpzzd68ZcLFfhMLW062/sJDE44dMdF9bLFfT4so7mmn8TAYtT/\nXbWj30/S4pSzjZZyx0W4xhu28EwNC1CnKgiIBlff7srV5/a2/TPaYRyCO3eg\ns+nTZIZx2L5S95yg6GmyjXkmItD7P917AeCuqN4f5SAA11ZrQDEQXOZuC2X/\nYScxYim4gOCkNn390Xmdc6bJNEWiJh5JCFagfkNV5hjfYpX13GJCeQ6+HcVk\nIGjnQFdpGkUHAFfgZRQnXeliYQeAOg83S5ifJGfqYyOfHqPv+h70owSvEUEe\n5pf3F9h/wRgeJ7F+yjsZUAdGE5tuXJwS5YZg35eFcgOPIKPIR2nsFJZ639f5\nGCWkrV9FDZl7CErLYLXI3pxvpxGkD5MEw5vsb9Gg9uPy+Ipf4pzPpW45YSLC\n1jUi\r\n=9bkr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD48Wypg0YsOnPg84zx+8F07r05flUUlFs5/z7NtgsRIgIgAdpoGXJtqDsrLGNCi3Zc4AKig0rTH4wJDlRLTNfPoGs="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.4_1591607324633_0.8921774904736295"},"_hasShrinkwrap":false},"5.2.0-rc.5":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.5","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.5","nornj-react":"^5.2.0-rc.5"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"91dc6fa0a3675e9302ab78722dc9d003092d4793","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为 JSX 带来更多丰富语法的 Babel 插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n以及类似 Vue、Angular 的指令：\r\n\r\n```js\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = props => {\r\n  return <div>{n`${props.name} | upperFirst`}</div>;\r\n};\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像 Vue、Angular 那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input\r\n        type=\"button\"\r\n        n-class={{\r\n          className1: true,\r\n          className2: props.hasClassName2\r\n        }}\r\n      />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx\r\n","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.5","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-WN5yZJOMO91tWAOIs7FVz5vjmLcYn9tELKPXoVtb9V4P/BloCdBVo2k+EFqrrgjL6K6DxqIjqYUgwaFsJDx6hQ==","shasum":"4ffa362d9ec4b3f3fb471fc2d05fffc8ec32f797","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.5.tgz","fileCount":12,"unpackedSize":47519,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8GidCRA9TVsSAnZWagAAejsQAJvRMglbi3J74T+MQgqF\ncwx4Z8nzl21F4SC1xOTYGJOjs6jNQq9Rbm9vUZBy9bHK0cUNdngEfZZ2WqCJ\nE4aveQsOH0SOe/+SsG81w0Y97lmPoeKDuvhe6IWsKSnNuXxbYRql8p6k5sx0\nuobvPuV9xyXLAghgj6x48slovxKV9oJ7b8NzqArS1GKGI97qKwVZrErrqgx8\n1m7xWcLlMzDB62mfYvmOTuEwX1afMhD5PXYtuCEfcC1s+cTbB2gLOpW337YZ\nsilH32s3+d7xqudvRZhBw+lZMHecRw2cQkPFu84jo7ic3LnWLP0m1jeR+fub\nMbgpipvQxjFa4mO8oiDPdJnqw6VfnO+qAYAiZsUNaWjDfzrZiPXehUUssWgF\nDShWJOxb0fJ8x+z7+xegk0vaNuLxR62vTwEpMlzklV1hyzpKdEcFBXcgxGlu\n1dLKDr6+8etE687Gt7Nzph2HpDXH0BM+HPpXKZESdKoV7l0cHW+w8Sw7qc0w\nPjTwT/lLO84xdJteNfvoj/JHxRCJwzlTwCZKSgER66/8F45XZFBzB67YA8PD\nLXsgFOueTKqdJQ3QkjY8O350NaQolQ9Web3grgKKR1+VI9flCMgmozY6eXWw\nnTusuJLbY7EfjjJtOF8ot5dkNPpCAufER+L089ihFmYdmOz11olF+0DFozVT\n2pEo\r\n=p6ur\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHBaRKtIH6DquH7yLI5mp45f4dmMHFgOUeXTKIPzqyQSAiEA7pLwgIMuW4yZqWwCntM+9pqUyJtDqw/ghSKwMQHdbfk="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.5_1592813725140_0.5109558386975221"},"_hasShrinkwrap":false},"5.2.0-rc.6":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.6","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.6","nornj-react":"^5.2.0-rc.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"a2aecb567593d0c493e1363d0a16121142e0a4df","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为 JSX 带来更多丰富语法的 Babel 插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n以及类似 Vue、Angular 的指令：\r\n\r\n```js\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = props => {\r\n  return <div>{n`${props.name} | upperFirst`}</div>;\r\n};\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像 Vue、Angular 那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input\r\n        type=\"button\"\r\n        n-class={{\r\n          className1: true,\r\n          className2: props.hasClassName2\r\n        }}\r\n      />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx\r\n","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.6","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-+cX+A3ZMpjvzmjJuBxqEWtsdXPA9eJ4c4GpKQn9horE/q0x06JMEQ58nf0WSLMsVHKnjy24P6uTmJ5qjba6ggg==","shasum":"5f4e41807881b78ce0a56d8534d8a77c2d6c83ac","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.6.tgz","fileCount":12,"unpackedSize":48411,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/HrFCRA9TVsSAnZWagAAaDwP/il5opeHa44cYTLik8CO\nqv60zwpZdmdx1JJdofVRbBs5CEiPJKC2jemK8Pvs8Ehxsl9N+RFcNNo9dMas\n2lWVMWJMxT8ytBWJzTCbPGmSpkBhL9mQQQV2yBNAARWarfR3GKPT8IIOXTny\nPfmVqq3rOMU09nJzoXSXZLsvr30NoOR09AyYuFV2Qq4ja25BeQV8gOv2UN+J\nHMv+BUk/tH2JJfSabDRFr1tNoQ3VcJ9KtwPTritF1c3EU8rlvKzCA0TWWtHn\nvbJGv4TqZYctomnleQOcnxj1X9pvCsWlw2vJDz+RL05ZtxHkc8eJLUuvgNEX\nywK01LQEvSKArxm3HU/PArhqF8TdRqvBGXai/vakviT4bHNkcINrGfvlrmXX\no1xZ32q1NzJg610p/rvVq9hwYgLMHFaya9P8Sh0f/Op9jrcbY9kZvPqQFi6p\nYqwWYwnqjHi8oewuXlpjxzc24fmn59O2B7Y2vCRGxDmGdyPICaPRRheBBxmT\nG4HfOrpDyCxlTs8dkOFaQw2dMcx0ZeIfBQ0loOmgRH/apBBbHxaqioRySye5\n1UoH4EbPHfk+Fn8RRGGKjEhu7NedsbCkH2h2CcxPpIxkNsTG79oH194PklCZ\nWH7+08A5AotTXWEYqzc1/fGsazqNChWxbg3w02B5XljckGHZxFcwK/QjmhGZ\nYJZj\r\n=lv0E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDH+03YBnnSkQaCqwF8cnofP7xLs4FMIJJa+0mlb7oOgQIhAM9cMgXm8FKzzcdQihW/ryGPW0wMMfo3mp+wnKLfXgHQ"}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.6_1593604804866_0.3427882443208017"},"_hasShrinkwrap":false},"5.2.0-rc.7":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.7","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.7","nornj-react":"^5.2.0-rc.7"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"b479428e2a692a09cead3e2d5af7c412ed3fcca9","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为 JSX 带来更多丰富语法的 Babel 插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n以及类似 Vue、Angular 的指令：\r\n\r\n```js\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = props => {\r\n  return <div>{n`${props.name} | upperFirst`}</div>;\r\n};\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像 Vue、Angular 那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input\r\n        type=\"button\"\r\n        n-class={{\r\n          className1: true,\r\n          className2: props.hasClassName2\r\n        }}\r\n      />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx\r\n","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.7","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-Xl4/Pidda0RPhCZuha29mgn4OTdLlyEIAgY/MMcu/chWTGWuz+5oY0C4HRJqYFebqgrK+Y3nw+vsFy/1N1XSaw==","shasum":"de1b24065379bce77b584b6a277b4a37df31d6e1","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.7.tgz","fileCount":12,"unpackedSize":48411,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/IVaCRA9TVsSAnZWagAA7bkQAJ9I+EEFAYT3t5H4iZzo\nutskrx7ft4i43SO8IjiFxgzE7uV0+huiuhjSaiDl3Y42wcYaoLK4Ul9lF+c9\nHidrZQBYiE2MsC+GHAwIq6Lkl2WmYTA0ieINc0vT6XvIUsZNyynz6nq+XY/L\n+WrAAJQrOBFGZIBqth/M7YvreleGJfz62/FflkXz7SPb88vllzsRSXhTFbDX\ntHLgphI9Bm/u6qhr7KFWgudXmsfL+BmJyL9bJ9vTGsLHrzKLzL6PJ4q6D72B\nmcO3aVHdsVvK6VgcxdrGl2SLc54MoYlBxi73MUuXFsa1PY4VX29FEw6f6s8x\nU7tUtagmYe6O2eBkE8uyEaSYhVue4+w2vOdNCoqqYoVlgcgigHwNVD7TERuK\nLzQBYmIIK0J2Bsvdp1y7ra1JCb30vfYEpSlpkvb3Apr2uv1QKr7S0kTAbbd6\ngiX8OqEVuSMc63523+khfItMnAyAQ9Uw39WUSZnYPXW5qBcf/pPBmBBPWhbZ\npG4TzSp/Wb8B6RCmzu0f9fwPapNrAN945kJrEVY4rVrwHVcsCo8lpY7eZoyM\nSAjSHdONVZV3CFRKByeeheBQbqiM+sHRLjRTtIs5RnBjEyQmOtrW0ZM9qI3g\nSdCdcF68lA56Ov9Nkvf9W1Dn0WrmsBTTh1GEOCSCxqL1KFrHrWLWGBO0J90V\nFRgL\r\n=0se9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICD68LpxHoXW5fGHFf7v5EURwsjeP/JR1or/OcH66meBAiEA495dcdFJnjn6HxbNObVXBlpCbJ41fty9C08a/bkCe4s="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.7_1593607514055_0.6884107073394188"},"_hasShrinkwrap":false},"5.2.0-rc.8":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.8","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.8","nornj-react":"^5.2.0-rc.8"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"9b6d4f07bb75a8bf12e2951140992876a16fa4ab","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为 JSX 带来更多丰富语法的 Babel 插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n以及类似 Vue、Angular 的指令：\r\n\r\n```js\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = props => {\r\n  return <div>{n`${props.name} | upperFirst`}</div>;\r\n};\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像 Vue、Angular 那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input\r\n        type=\"button\"\r\n        n-class={{\r\n          className1: true,\r\n          className2: props.hasClassName2\r\n        }}\r\n      />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx\r\n","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.8","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-A8kU7ysAj4ystdgFxj7BJ5izq4MRCBVzN0SWqkbeM65JjngqR5c3/Ns1smm7bQefnj8k0kCTVWhd72bGwFQPfg==","shasum":"b15365b1643082d5261452014abccbb1c59abc2d","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.8.tgz","fileCount":12,"unpackedSize":48411,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/IpaCRA9TVsSAnZWagAAqHUP/jrQGGVhPJqQ6D2NN9A6\nd4JCXcaz9nE56YZ+ep8HzjH03vEijJbB50lhb+jsJWh4NKHW+gGGvKjwy4KU\nGrCm23vgBqYpyO+mptF2+mQXyFmrv/DxIbFbB8Mw1b5+L5VJGBlShMLMVb1L\nhfSHoeWQeHh6QMJCoJgjCdqTNTd7seSboXsIQ4pezEa0sJF+uhVVTWbBMVys\nrO7heVsGQFdmYxg5ECZHKCYg4QHSfkX9fUAwZxMKFdfngTVk0nFCWR9U4k6I\nYziW0D9oQ7fBN3tVK9USq69865NtVV2z34u9ffjNXh3BQiW1WAgi1qP6S9PS\ncL8InmJ8gQv2TLb+H6mUL9s+/fhWabkQAvDx4ZvsbzObycuHZDGBIkxcrhOI\nhBwKCZ7E4njZUrQ5xUqDbJCZNQryaH9u9m3sxvY5RRl0JUxastK7daRJ1HGX\n4BdO8OCeUzVW4jouYgtIPofPIY7J/l3WFK0uX35l4dWRDezGv7yUsvKBy3fK\nX5xfdAy3Rs2su5K1iQmZ6VXCv98pvoLCuRGJ5MTeP1oiGYESbTVVhz793K0c\ndvKg7oEW4sUBlmv233VEWzyHyD2BelmhGuWSqeQ0m+8llOLnay3mCWWpNVas\nWRkhq2/K9LA8V8Ml5Er6dIkKuuZIWeWPIxJU5wUecCQdaUo7u1sPXJ4oztvo\nJIz+\r\n=+2YV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFrlhFasG1KO+EoXqId60O8xmKnlIxgs66Xry9KTAD/eAiBbd7tRzQt8jqhLZi9345sh7IlLN9/UBvNGKT1uXZPozA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.8_1593608793652_0.5973793863017067"},"_hasShrinkwrap":false},"5.2.0-rc.9":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0-rc.9","description":"Make the NornJ template work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0-rc.9","nornj-react":"^5.2.0-rc.9"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"8267bdaf7557dcf3cec7d50e7cffeed6b2033d16","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj-guide/\">\r\n    <img width=\"100\" src=\"https://raw.githubusercontent.com/joe-sky/nornj-highlight/master/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为 JSX 带来更多丰富语法的 Babel 插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n以及类似 Vue、Angular 的指令：\r\n\r\n```js\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = props => {\r\n  return <div>{n`${props.name} | upperFirst`}</div>;\r\n};\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像 Vue、Angular 那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input\r\n        type=\"button\"\r\n        n-class={{\r\n          className1: true,\r\n          className2: props.hasClassName2\r\n        }}\r\n      />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx\r\n","readmeFilename":"README.md","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0-rc.9","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-fkx9lDSqGDk3Cs6XMhqQ7HncyXNXNAVC9wzkZkDU67RYiBRfcodtO5usApdzgw0bZtc/r6155ePvjNddl7se/Q==","shasum":"9f887502a90d76cad268f5055b55579def8210c8","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0-rc.9.tgz","fileCount":12,"unpackedSize":48504,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfBGb1CRA9TVsSAnZWagAAepsQAKD9kwGwUARF1DDE2yN+\niSYp2ut2q1ZY729eZnaLi4f6IMeaatMIs2+yTjtZRS1NqXZosjHSJfgqAfUB\niY6FOUJ7au0zjMuqsC45NLgbty42fZYVxyZViSvAutrUfxQ1ItC30fPXFuSH\nQZNeTxKUhess6vNC5fvTuZ5vm2J37oPxTHh1yFcKJxGkisF0sJ55b45glT1f\nptPaYXAkyzyy+bQHL5LPLnS/AAeIUvOWPnnZxRhmoEKOW6KXF2u+F473kSiK\nIEImv2i7Xb+l2sczJy65JJp50bpykmSbFLVaTNQHLobzvLZXM0oY4PbTkybr\nbANPbsXtUFg0r5f3aed5di4UTmewmho4/93GecvvVP4aNk0kKGAztSK8qeR3\n5nyfdRqrM2Iqqc0ix3bNPYt8uRwmms5NDFlLPYRyyZu2gQ69bEfqOqIXMjoa\nUP9IMqSsl9eSvS52J961ceCqUbjrxuelIe4v02p+fTD3XuXu1jp/x6AfOxE4\nKqppTFEVL5qn8pYaGY/9yqdGqlOCLBPshlQqiZh9vmb8EInIqW8FWaxlFjZy\nLXnc9OdH14yz6ixzWM97cWlSnsI4irHTbU5XNmr9t3UXVwiVxy4Cg+KJ/V31\nvgMLA2ucfEEa8HzvI5RxhI84w40Lnp9e5d3vvj8SY8NzkW7u6KCMonWDQMlc\nYk5F\r\n=hoMZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFnbJRKhzSzudFDdcUz7+drC2fjKcQaOFkxQc16ZV1bXAiAod6YgVt132Mt78Vr4a1Gu3NL2R3u3yOrQtI5sh7qaNw=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0-rc.9_1594124020849_0.7042694812399561"},"_hasShrinkwrap":false},"5.2.0":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.0","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.0","nornj-react":"^5.2.0"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"b13dc85de58ea00ed91757298298009ee0d905ee","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.0","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-hkqgGoDw/GV8GZ0FZ+3co63DDkWYIx6D5xNQhu7dj+fAL/9DgOuROMsv32mXduWUGHz85yyEm2w8PQeE9Mn4AA==","shasum":"6c552d7fd2c2a12c60b671d04b5919d9d7ee8dc8","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.0.tgz","fileCount":12,"unpackedSize":48573,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfBcFwCRA9TVsSAnZWagAA/cgP/2oaI9Ip2t5zLSAkRlSA\nfkHWEaX27Qzek2ou8iFio03LVg3hfriP1hclM4qU43Yuhjhxu2Ru+Njbk2A/\nJBulwIfQCsPrtahgvQTaUzTtZiW7B+EgjDIU+6z11eobBkXArWWYJvaIBSsb\ngCEDDHBqxlMSFNv7KxTZwxlT7Mi1q8Q4R2iLwQswnNb5e+U40VKAs8DlmJ1X\nkqUauIufVlh7fYkbaOWniGVKTSpShnp4oNc2rlPFsvMCzCJyhMclcTFRkx/O\noKqOwJqeGHKZ/Q1YN+YV4PVWr6scrKBSDjGakqTa5od8n0JM6PZTLUAFmK3E\n/fXd+wW8qt5sU9SfqEeeFemjiHnUw4rdjBIuFyJsdmcpVygtISlkwfn7ReT1\nFSE0CG4+38qVk/QW8cpQoBn3fFmU+D/9aA51aDJeNAOb+DqXv7W8BrrUzjg9\ndPFGWZr360vbkl97L2sjISvp8J8r73aPMfEpE9ob4IYwbtgx6YVJrE5jBvvu\nC6FKfEaTceMKVoq9cHqvDZK7WZZNDyD2BT2qAL60wYfmompwTi9vUF9zT5rg\nacLrMlH2UC6KycjVJ/IFXbHv5EFXZ4NiMVvBAtZ3AYdp1uprQZusqBFTIzM8\n58OdzyhqAQ9drwXEEotnRbKXUbmDuyj6KmB2vIWXRiyA2Rrsl8AOmOOA3HWO\nFx4Y\r\n=PdOA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChOiOuynZ6S3AWPTz4diGNyQaSm5j6lTu/PoJExjMOkQIgWEKeZMLLEcWAPR2RZgYBFT727ZVZWIqLxViwV6z7DUU="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.0_1594212720265_0.5457610424963366"},"_hasShrinkwrap":false},"5.2.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.1","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.1","nornj-react":"^5.2.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"cf91ffae0468c4cbc17b29d5314ad167d69bb37a","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.1","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-Rsl4bo3mDONvYC9lUX6/v5djCtVNtuFdgz5xJEvucPfdFZE5Da7s4wOJoOA2Iw6h1XvYApoKE09LheWwRMlkXg==","shasum":"ca5e0345aa0dd1b728cc6dfda81744cdd9b76967","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.1.tgz","fileCount":12,"unpackedSize":48573,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfBwdTCRA9TVsSAnZWagAAg9oQAKRsBFSCw9UUPQ/EePbF\nQ/Zw5Qs3qEfXv5DfM5ubMCMyvX7UAy5NMoE4+q5KI8qKKroF0NKJlVFtmz/T\nqWYgkqL26JRV1LqNjS/N57vGBbglwuSonTFRXoBG4o/i+auZ0ysqHK69AViH\n2vmwNeuhAcb30YmbTb6wjGiA4N1TNV0KAp/I9zabwewgxeIQHpoD0jTTpa+0\nySVbXJNZNxN4DzIys+Oo81ZvpzlgZQ22PRJxcg3CNJIY1MpM8TfbgbDGOqwh\nsbJkWsS4qqfjLuuhLQBMfVRy7s5oGrfwdeJNLj/UQ+fcsyMvz1E+OuQSz2SD\naJkXLJL9czdfIYN/3LJesDFa0Di+zhjviJLFScSceHUTaXguMNFYucRUX9Ea\nPw1mw6dnvMQ2tPL/tsVSbHhn6UpVUSRD9s9UXxiO0ARMitoGYwHHUClqEkxS\nvNEYoMrA7EihnFBON7ibxeS1MmU/jVXPC8EvVobv24cKI34Y78dwtigZVfSv\nYqL/l6NRxe1oP7IazdX/xLT+R0y0I351DAm9p1BFCIjlbUnu4r4frRKhthKl\n3yMOiX0JC3f6m6/Qs2aRydIfNjNN9CseC/oj0F7uoJoYHjDhKBEJW6hlb4r4\n8lUa1xXNd0HMpZ8w5zlKpgmQWtZpHnsNu4V2Rz+tDY4S9udXMO/UWhJDJqST\nhImU\r\n=qsLz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEvGskbibeUZfpenyJuo4J6uwkiVt1OET9Vh/vYnvFugIgFUWUtzhZKosioTkVPPFjrWlGZXFE4TsUM1XlTLNpLc0="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.1_1594296147182_0.07893554860757868"},"_hasShrinkwrap":false},"5.2.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.2","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.2","nornj-react":"^5.2.2"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"ec2de7f5ea93ebe6f6416a98370b2a8065b49914","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.2","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-RjRxuRPjKvcuoKCghDSpEr4eZDH2moz1fhQEcpeI4Ik0le/qGW2yTQtvL7EpFpf2xXSP8ifD/iMqJ7cEMNbvIQ==","shasum":"bf7eb286c122b05e1d51da53de1cc01883f4dc53","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.2.tgz","fileCount":12,"unpackedSize":48534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfFWObCRA9TVsSAnZWagAAXZwQAKNfnvu3lTzkGoF4V1RS\nzsD2pXa24FAdJ1QJS0AD2YWhR0iX3bPsqyhrFKAk6AdTGYp9AZMhV2hQnA6Y\n6NjorPvz6IbAzJx4Cb+P1Dz1DpAyfI0gRsN+vIZFjcT8P4DSFyog2lsg/Ee3\nrFNetWMV9KseCQnPcp0DpKHiy01Q/bg97cCacwT6SBA7BipspQSx2w8WMwXI\ntv194NPWFpHUxK9Ce/5/DpS2l1v1XHoDeTxY3QTJOZ2skO1B3kw4Gg9fE1PJ\n3JjajsIAJDWMRz6tvQRHxymEgfCE82gfti3PAmLmfQDflFOVuO+4FlWRC9kt\n2HySEAOrUMUkD0W1FSKi86MtEh6VqhN+76Jcpd4ilkNZM/GGJ0S0l75bKG8B\n81BPdh7fpfCv75gA1yPpQZ05ZofPGxpntDHn3IWrJ9RN2Ff3OMaioYqRGpAR\nCHzYHeXOYt409V+GP+hznHkoaXmz8J+rzpoY04w0J5Wv5peViLjTGmSmieUe\nzkWg87xwrQztKDLfGBuqeCyYuHrpYPsqEc/+LZn2me5SCNAxDTbJm69vnMlS\nIPYSJSaAEtSLcUBysWinsqo5iHZlKPvsBqRAkYsOZc7rXz4mt7K1SQOhNwUh\n7ky6RMZbd7oH79qWJ53uxftYdijTaLh70rL/RF/ZsjszSAHUHM7PB6VWgbzx\n+znH\r\n=Uc9E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD1itQbZ2D5u2siMbLsuXeqd3BmrkbEMFj3e9fn950OAAIgKWfdtFqX/kEmUyhDZeJfSfRYXdPxaiD5cPsY+Qc/N7Y="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.2_1595237274794_0.7882067375360364"},"_hasShrinkwrap":false},"5.2.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.3","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.3","nornj-react":"^5.2.3"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"2f8f12968027265b326264111913684d07d139ab","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.3","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-PKyxupjFaz3MroQF/TgLVDs5X17yllrk3WuaTF1A6H7Colk3CVQl3VYEYealSlsIlvWo0tlZ9zaB3qITqMGbSw==","shasum":"5ef2cdc81086d770d2356d50cccf5a484a9a8019","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.3.tgz","fileCount":12,"unpackedSize":48534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfFWiQCRA9TVsSAnZWagAA4mAQAKQ32aDl+a8+cSTGSF9c\n5EbxA53e92QmO17FQz0WKkt2vRDIZ51fmW/ACoc6H9nBeM+Y25gmbTl40Acv\nvi4UjZdXkobrZ0ixc0kiCOERQ4zUrgSSXZrUB9SfzqByzjqzLhtqFcrFtTfR\nkXsB6b3tq9xyBgbHP3PN2GABZiLgNPz8lUr4AEx3JPQwJQnrWNpt7BRppfJ7\nEH3/yvcnklz28erDbmNCU5GP5gLqoEJTgd3BBbzsGs+7UQgY9CL+4G+tC/hE\nm/yhpgWp0H6UHMKAY0/tJM1hgJPAk9s6k4fh/JWb4fMvHtQO7dAMSTGWr54A\nd+7X2x557Jp2Mhmf065UEMZfhh2lNHLPr6BXAYQtRQlIyuq9TsWbj7IGawKI\njUBMSObK2ANZQwH6HvzYD0Tj0WdcYEJLk69dMPbjEWnoITdQIZ/QtwDwUMV4\npqRfBrbnHmpbkS/lV0w6rSF61aEATdADnFh6aIOugf+z5JW43Izbp963AioU\nGqm6GCUWfVi0tf21+mB7FCKZ9mE6JouepbfE57fKB7hkF5Wj0C3pCrHfKxBL\n9taNQDkjXStT+LyrJQcDS9JiArWUzxKtibC9B6U3w5Xh1PYRvaSicPkc8nu5\nllYACWbqq6Di9NJlXqnTvBu0/1F9HyQuocmP/zrMefnBT31zgy27tJgdYo5C\nuOZL\r\n=hdoa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCMvrv6eo/v+NeEL1aFPCQ8wNtwYpWDqaohD3MnT67VEwIgNk2bljb31EheanSuW6Wmkk1OCDIqIizxJ7LjrzTZoew="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.3_1595238544098_0.06255446660453412"},"_hasShrinkwrap":false},"5.2.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.4","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.4","nornj-react":"^5.2.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"1091f6cdc1bddb8ca2849dcc295735994853aedd","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.4","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-MKeby4m1Mg1i2Xc3D+uHoZe3yNeN+GiupRicJqISM/FKWoQwVYvXGbckIUgInbQPoCt5HTbBYSCm7YzmmZ1EkQ==","shasum":"59827acde28b664ffd05bcda76e32100b8bce5ff","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.4.tgz","fileCount":12,"unpackedSize":48534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfFXkKCRA9TVsSAnZWagAAecMP/0NeS3BoySDzlzjUbOPH\n5z00U7Bx+1SUlWAyjSTjpO61CUREa03xuabHLEKohsMDKbtiVuKWamFBRBQ0\nW+4waTr4ogsBktEaBVHiOGGez4yLeCYLFVEgZaLfCaoMpewGSO3PZPrbelcW\nPY/rbIKPcZKaG0gYybOElSJ/1JokpFNShr33GZnAj1xLq7XdiLKw33mU/BjV\nXj17nZRTXqEuO/z1h8NM+iKB0D38VPDX8K1tztnb889gT8A3xOJyZN1Zaj+X\nbypOz6gN4oWPo11PtL8N4IV5WNH4s3fGE207MGOja52pFhgL5aN1oCVtKjFg\ndmLhYMJVXXQ3cZ2O9zyoujag4iRegsVg/gC8SjllZBKY26bwGO2wnr8642tN\nHXx+tRIJZ8g9lg0QhkFLjACx6+NCoCWleEtkikmbx8cueSJBJJaMBjYIuAPP\nUBMu2VOrc9M/d3mLsxPRBBP2Woi6r3EBB/1aj2VvGaBJrO98UxWZAYonQJc0\ne8MwV0lhoGrgBQ2aU+wTW1OOVBIcFQzzFR+TXiDdEAQ23XEqRqtDnovK/aI1\n3Tm9Vy2RDbmBB4HOXHMgaN/kPhqNA1kHqXsjGoSzGGZ3szKEJLQH8Lt5b4gS\nJszmdbb7vmpBXjUVNBKv+VU3yU3UE8jgj2Y6Eh6dE1V2AfZuzorR7pz6Yxn0\nbyCN\r\n=SSpn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCFB/bA20g00+k0ywARnxdJ6Ggab9qj7rKGekSqKTEQmAIgW0fJleMC46azjg38T15lkIYbKHgcCvLiBGE3OPAZl/4="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.4_1595242761745_0.8452546393619254"},"_hasShrinkwrap":false},"5.2.5":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.5","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.5","nornj-react":"^5.2.5"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"580a23ea0a9b4f864b4856804f1607245572cfb2","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.5","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.18.3/node@v10.16.0+x64 (win32)","dist":{"integrity":"sha512-wsxH3QvAPkxAPprRksOvWizH4PPntA7KL0Bm+n7ahpQSbnGwnVuYtG9A8j0Ep9JWYMiOmCqoLSixrVcFHZPsrw==","shasum":"0952ab140f05bf6ec917744c29bfb61db651c153","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.5.tgz","fileCount":12,"unpackedSize":48534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfK7qHCRA9TVsSAnZWagAAB9gP/1wFM6V5XTn3XA4WB8Kc\n7obZ+vQEC4+w+C2h+9FLxJZkjFwsN6QIPcP4qBJ1QczLO1nT165y6oMF4gqE\nzIFWtPdTQ/+F8c5Qztm5xwv07O8gD+TcyZ11plR+nAbbSXaGAurTr2Rb+dYJ\nOc3JvwW4mMvojFujEehNrgFk7z1PLI+AIijh6xA9HBbszEjRCbZSGjdPpP+G\nUsUJja8YfUZLL/22q9DeTxjWLqmkqyeodFBMVvxhzJH6nx5OAGun+QKv3ioG\ntstS3ee3Xf6K7YE6+w+lTywq5VLXAEEGEzGgPWk3yX8mcMDIA/qfQEhhPYRh\nNtI9QH7O4PRUTozVnAY6fYQYD+/NqUwuMIzuXmnXShcycQimNBT/uulC07qP\nzwuMztHWGqFhuuM2x41ayY0fIY6ZhQSWHwfJfZF84LJkavtfu5nhVIc66/E7\nDQVa4gnud2pNRqI2Kylv4yqTZBLPZbdtf1VVIRTXVnHYjrv272gGgSWdjJ5m\n4B+h+bbV2iphmARMJS9gjR6U2uZF0GTehUQOs1UnmGLiFvdO0ou7kkdZfaK/\nlRmztCGqRGPPqfnd/ZLizouYCeZDMCDD7kXR98HVNHbbHp4O+tLUCHhHGQMx\ntRi0BUC6xgyqsX+vZW/zBR9DXWgbUYsaSL0XjMe3wWSFhDDupy5Q2Rg5zKAu\nbQDZ\r\n=ECrh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGk/tyGh1tU3fDfytNe+n/oOGFR7YNdxmXjVjEf0ZXwPAiBIKThW55f69x752tfbOX8YI9qCWspfe61kJqPLH6R38w=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.5_1596701318901_0.014753905390302968"},"_hasShrinkwrap":false},"5.2.6":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.6","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.6","nornj-react":"^5.2.6"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"a93da691815ce1bba690913f9330803f9d7bc43b","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.6","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-gSCGqwMzzbLXHEgOdCQ3RGB7KqCwSU9Pg1845IA/wYh/ego8OJkZuJ6v43oSiigfDsGpgmmHoe8HW9fxZqjlkA==","shasum":"cb5e1af6c57325d3293d14768481e21b082d4708","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.6.tgz","fileCount":12,"unpackedSize":48784,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYc5ECRA9TVsSAnZWagAAAnAQAKUvc6NWuvXoFIlKVxBr\nZ8Iup8MBswFOV84Xhm2PDyu23R3o+wlfrNrTEMwR82QqEzZIw2YVMnnMrw7/\niJ8DDh9xZd/BsSWEZbzJhLkm7ISRqtAneb2Lg5qxCcA+No5aPpwGVZ9r5Eeg\nv0fm8Hqpi1fsrcrkJotJFsueemY343Yila62hFoMhE6S7soClNzWf2ipNFXC\n1NBIlUhJnoRBRuzFPNBLv2fFhO4ZeSzncbDpI1NgtFWO9GqCyFibyY9OkG/r\nWRABQMvmgeESGaybYQZM0g82lHWa5HLYhEA2OPN7sEUcGzIRN5rBQ0KxTvF3\nV5YRS0ijd4Z5Mh3pegehNIl3VmomRZxTmXlkDlbreJf01BbrwnbIZAoYuhp0\n9mGIjymyidiY7bOW3RjwEMYSovJdT121DIj7MUVbzqWScKq4qB+hy9qjRTJt\ndu0zOpxmxR8G0ioAiOMmKfuM6Oqhfs2GLTBUXdIbq2Bt0eZ99cmpocvC9vCE\ndFhziFbpTLuOTC69YEkGDDS9GG4npPSzMxMHZ7lZmr5UxtFDWVayj3L+pDaH\nkVRawZP457O8PvnljQxnfoCb9s/iKtzhDUrsipB21pbRTWyjpZ4CEk1D6eVV\nDQgeW45rf1wxLHKEyrfOVH8pjBcboCuqTmIOCOTSOpHhM0NGj7Y32drGXFul\nl0qr\r\n=T7fj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICehA+pOXt3hiB30BOsHaLJ4GL2vUeUeiySXxk8DutoZAiAYUKjEVwbENmXDDaktFMbqkERj0qyTSCEPHoDvSUDJNw=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.6_1600245316337_0.42738981917135344"},"_hasShrinkwrap":false},"5.2.7":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.7","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.7","nornj-react":"^5.2.7"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"e51f20202da5d7e25a499846bc8a8db5cd2ac2e6","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.7","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-vUKu6rwmUAGYBDJV5jARqK6wCC0oz5bCMbXJZKoEY7rEZfXL87lCSmaA/LKfOLLX27dOBvVmZYGU3qC8m/Khjw==","shasum":"468290dd3636896f113507383453b9d6033fa1fb","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.7.tgz","fileCount":12,"unpackedSize":48833,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYdPbCRA9TVsSAnZWagAAa0gP/0S35erjTzyy+sb/odWx\nmfsvf0Ex6YNqgWm61Po1YW/C1Z+rqdvEkzajZX6wtGq5c7MBEGNnT7KwEURo\niourbX6z18m864ERj2oAhphosRbSWO58tKlTRgCAaGYLFaCrhZhq9xp7mN23\nOdfFITEf8G6ax7i5YoXnx8ZX/9esh7VpxW6LLCP66O8gfiNy1y4quYXKu80p\ngE+l5qsJ73jsRqMJgdjteTUK6r5VjED6Lwmk/CxuoTYbYfeVqu57sYIgp+ky\nQdnXjHA9cLAu6n2TJgUOYWMEhJZx5bEqwhNWCqABH2f2k6KFMUpw7osSDI5r\naK1uXxHt770ZEBcGz+Go0UNCS45QxRSQMoPHZE6+37b7eYkOU3VxJq8WmPs2\nAMBC1Ejx7Blu/bc9le5oIIYjEjiSDzg4JbTkXKhW8XTrjgb3sr/jC53QqiKX\nwxdEQrzAygmlEc9QfUhAVe/M9dGA+KESP2vdFubVpCfsW4MtDELhb2/YqqaY\nMmdtVRlJ1OAPZscaTR3YY0Rjmbc8sl92ZGjY1OknGOq3rt4JYhri2KfIBUKy\nD0Kr5d2RVgpNgw9GG+jSf/1JzL+q5tRfsAVVfeIiFVVL93UqPcX7GKK2+jEc\n4B6ls6WCKF+QaB8cFplST+pHFQeY2cIyckimiBiUiH/CEriBCcfi+LWtTdva\n5Vun\r\n=yJM5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDZGm9JSEcZ0dDSavgQmZkX0R0dMD7XTNJUKY/DfGTtdAiBZUuJn+aNTzY5tyDui0EAZt4V+82XGtBsaFugLCt40eA=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.7_1600246746729_0.4135605248588532"},"_hasShrinkwrap":false},"5.2.8":{"name":"babel-plugin-nornj-in-jsx","version":"5.2.8","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.2.8","nornj-react":"^5.2.8"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"c52ebe18699714aa6b057da68dd03d32b889c36a","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.2.8","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-ZtsF+dSNfq9eVbbqEhHZsaNsuD9NJV+sCvm0hZ+31aN/fKz4S98j6yWdudGcXITlMYDmhXBoKu5loBLgulMHZw==","shasum":"5dca4f3350c9f923468676403f58cd00b0521995","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.2.8.tgz","fileCount":12,"unpackedSize":48833,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYeuzCRA9TVsSAnZWagAAUZQP/iuBhA0tCSfon/do0xnJ\nOTdcikGZvfV8doy16IlTpFueoZFKUh+9EZkprLLeqMpfD6zm/TiC7KWU/ZPd\nuPMAxFffbZYHsn3va1btaoAFh+WyKIoVH2BdRPC3QQYkzqMm6ZNjL6l2dccf\ngdRpSzYwlAnYaGYIqDSbQp3MjdsVfu6+Ljvuu9Zk3NuO+qJGLfLz6o49/VlV\n5Ssa6dovas0JmcZUa7/Ymw+eoDiq1KMABuBQO6pKfbgB7qxm7IGO9IhP6Xh4\nnytF+CRPl0ZJ+O6MJYV8iS9/BJPBiH1zI5I9RPnLNBd/5X5xrVDa+T9N8Dox\nqGTYAw6DggdTs4H8E7DiFSx4H4u9PCLf8SlpYVlikbwuGeLPwX0XwLaKRpWd\nj25B2waaIIGYKZgd+kdLuMLeY77ss7oz0/ahq+71+VihPnJqkD/euAN4yp82\nqUK0RuVKE3RtS41RR0un+5o8IvQsZO3ke6GVQBiVEKx0hNVzFgsgyNxcREcO\nocr/COZQNJAVPSVihe0omSuU9Gvduw4H6s2pT+UuHV7cU2QIg/SBFE7djNGw\n6ixqtzdrgULJI9KEXUkvwFR5/zN6xmlug0gaOmqyxZZe9kaytkPA4ayo4CG2\nf9bQJBBuaUeX5OC3hC+Rjrck3QIVzxa4QLx4DQ20OaX7cEvT6VE6//oNHl4p\nivEL\r\n=H33L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH7bgjQSL9BR3Ue6cFYhr7Ski9FiVMMELq4BTQ4vVunyAiAeJYxSmc2EQccCEzW0YOOKt1nfQuPuVNh80aFlchzlfQ=="}]},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.2.8_1600252851073_0.02013552516308259"},"_hasShrinkwrap":false},"5.3.0":{"name":"babel-plugin-nornj-in-jsx","version":"5.3.0","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.3.0","nornj-react":"^5.3.0"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"dc423d34e1e1fd21e0c97c7e5ef140e5a78ff936","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.3.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-gkpA5UehBkVE/uACMQfvNVJtf8FjWLGii38r5WiB27Hs+mGDZu1ECBYoNYIaVQGRCvqiT0cGIX7MsoMNWjLzJQ==","shasum":"23698801c15a266f82206d44853ce4c2e5e46410","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.3.0.tgz","fileCount":12,"unpackedSize":48833,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf7G81CRA9TVsSAnZWagAAUc4P/iEJSshXA/Q0N4dz6GF0\n5mwrq1nCiPX0QWhQJyWqDsu/oGZRN173hMogHRZaY3SYNk5iUprPor7fxZ3+\n9P6nHhJhp7ZMI7y/Cd5MIc+WlamKHTfoTyDn67oNYJytp39knFDewhkVhsr8\n5o+LsKu4ldRxlgaMLUN7p0RaYxHWdLVVX/KuudKp8fA8N8OwqS2GBlzYxYp5\nV1DiE2Bp3MTpFPIUCr6RhTd8aicb95o7zwPjcEsybo2EYGkq028CM+/yMQxo\nhjOYvxvijKc0rTEpDq+JR1xKctuuN6ayoUZqJXw9jpPrSIbmOTn3Jem1w2oA\nGNL33vh4t6TP33+GwHi7pTcovax9yVd0BVJEQPde33KBJrIgJWzYq3dNcVyo\nf8XFoqFTZdKtxD2JwI+A+Nudw82JSvXfYwVDr5x8abFfd7pNa1xy2dGfpFzF\n3kbXpQPEga+gexJw4MpNhn89CIRYFmtwNRVO+SbnSdON8T5xXW4lbMMkpNxP\n8pRzYCk2mB+5j6ufBMYtYi5/gZYZCPp5z4m82kKSxrW3ZUouy8MSJ/XXNwrX\nQNyqb4zy0fG86v52FSq30pzppRcyTeXCPQyx9W+mTS3OWZ3Vfk+FnrQhncGV\nDxSWLWs1JReScch0MeY3PYQ9l/wiTCh8dQCGRU/4AZo1kc8v2dv0AJItmXJY\nvvly\r\n=3T0I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZVnE/s8qgH0CYr0wGAoahWAyHUo8EdjVUIlwV9MHIhgIgWIT4KoWi+sa4a2Uv0ljzjR44aPwGgiKvjiDo4QgvAEg="}]},"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.3.0_1609330484820_0.25606780534144025"},"_hasShrinkwrap":false},"5.3.1":{"name":"babel-plugin-nornj-in-jsx","version":"5.3.1","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.3.1","nornj-react":"^5.3.1"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"c6668805278747d4edd7b8a8bec8e813f619ff58","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.3.1","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-tQobsyJ1B1KG2WoxZLkaqbumslmWO9vl3bpQzVGm1TUN8u8Kd4i9IAidzMkwy/ZJR1v4NISUg+XrTmriV8OPpQ==","shasum":"31538cff6b39334df1ffe47efc492b66177cc1eb","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.3.1.tgz","fileCount":12,"unpackedSize":48833,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgG77tCRA9TVsSAnZWagAAPPwQAIdQ+Xz5ysKgUz6mb69Q\nmcDbCgoQkLEzJueY7+mUfc2HTKh4FgoPXhkA+tGV2QrWLPmE77BXcMUe3rxr\nYAlOuLk8AEFUZ0lKgEIDG5Ov2l2Yk+064JnZHwRoF+cm4HJfH6MLg/QUxh8g\nuJtHGz47N8Sm3kq4JMkDSULvkmpo2BunZrMtxdsF1vM8wV/xjePmDTUP4pnQ\nveOg8Rig0CQdmFkX93K7j3KubFTPzDrknTbHOiQ6CtaFcCT891O1r5FPBJYe\nb2IZCRskOZ5jKKr19Fr3R05impjPqWnEjKFR/GZgkeG5UoQGDM+NRolWEy+r\nSAHdoN3pIl6CBpF/7NGNkK0IcRVyrLdAr/LN5QRlC9972n+3R36evpSxYUy7\n2IVbTm7ozsS8NJSBn++ZCY9q1x+iqUSVtZSOiwULTJzDEbYxEuQYoQjlNvH1\nOH9GlTbPHyNsn2Mkhole7z4AE932OsQlpdVHow7KFcARzyLrWCIK3parKOIe\nzkr4gZTGfzprayJ2Tz+8t4qBfE/Lt3oxZjFL8FGV5LM6p9w+4Dgswr2nnK1Q\nGbPcQHHXEtz5Mt2EAoDgtcFxLoa/BV2b8SDnJdk/zi9wtFP0i5EGZbwqacNe\nakcB80MUmrXNlRkN0oPG6YMWqTL9vBv3e2jn17SdYanZ/ojmqdQh2xGwnzJT\ns8rN\r\n=LU4W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDsYA6wjAbC7jDz80V//xaKLacnTn3FSCSXgs5jJKAe/gIhAJ3eEkt/KKGoEUVjDk7THhR3Ssy/4c1RjywyO7cFjweB"}]},"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.3.1_1612431084582_0.18556896567275705"},"_hasShrinkwrap":false},"5.3.2":{"name":"babel-plugin-nornj-in-jsx","version":"5.3.2","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.3.2","nornj-react":"^5.3.2"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"1dca70bf39e6590d40a42e2afbeaec9434f16bd2","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.3.2","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-DXp5qY5Hr1MXV3A/FAMYaSF5osB3CnFOPesgcocHS2Q+5FUZezpxcUaNPUuOTiK5QWTQminzMXV4J6LNjH21DA==","shasum":"d68dd138acf563266426f18d1c4d6a84b09ce615","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.3.2.tgz","fileCount":12,"unpackedSize":49041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgH5WBCRA9TVsSAnZWagAAfGcP/1WDW3cdd4cveG/GHEBz\nNnKYOMaxXlHbFTZKeC3Qq3yUgtBlDJztV9mhSSvv06iPT9FxXYP6vRV+e3QT\n4Dd+0/HcxYZc8vuzsLcEvptLFuFIOJFEfmlZOL+xmiqANQRQ+4u2dnlYMpya\nsZXv7azKAqchOosb+Fk2ZVx3KBRB/HiV8YczrgPCeIYqunsFWV4M+O0RaktL\nn+P5st5M6Y/PpznKR9R7LGLHSuFTpQ25xwHoB865tpmEw1501YOqz/+XCtNg\nDq0pBpS4PWDxeD8BquQhmzhl4B/EjkwlKYap14irE4FkcdiGxvtj/wPOYDVR\nZYelN9AMVbqD+IyyVtZamJ8UniYSFdwsO9zzqWkCiSiN/cFvpvfBibuPSosx\nafEaulGMAjCyohNblYnMilZpCPqtsT4xI73Z1s7IFIUhgTjTORAEoTt3Vr6r\nkqAhJIftSgQ0uYyvG8IOS/IomhyHQ/bTcN59JukGUafj2eQRRAooi2Q05xcN\nItq7eycnWH69n6ApWhx03IDMVm33s5H+uTN0Gqs2ZtxRs0lwZ/FwUYUcdRz9\nWieezO7JzurINEJ1z2LBa510DeH2/qrXZYU9yuM3OJnUmITWpxXm6qLwu3/z\ny7jEMrnFC/rSD6sLonVA7ZC6LWUCgX4zlicBj3gS6xD0O9jNi+FN9+GEVxeP\nZz0a\r\n=sPCH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICLJ2OrKYCEPibxr/+3W0C3ZX1KiyeAjBBUHwZadqzieAiA5iSIhN7IluM4Vc1Vvbjz5OxHMuWssYi0ytZRuuMiZZQ=="}]},"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.3.2_1612682624667_0.956162863547872"},"_hasShrinkwrap":false},"5.3.3":{"name":"babel-plugin-nornj-in-jsx","version":"5.3.3","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.3.3","nornj-react":"^5.3.3"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"a9fe908a045dc2a3ac7d8a8da11e28e8f589b63c","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.3.3","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-+PFTo9uyFXCfEhcueC/HfcPW4o4yC3cKYr/j3dizvBsT+ir2Qi6RAeV4U99XFEFuYvBN1oGxpe0kOMGtO+KWPw==","shasum":"fe3514b3b4e4cb8946198381ec598a3ac0c8c58d","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.3.3.tgz","fileCount":12,"unpackedSize":49041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgnOBmCRA9TVsSAnZWagAAF3cP/35GpnIhXEVApx/p19HQ\n78hb84HkIaBzU9qt8cqd+9zyjIoRPOGo+elOD5fts2ubbNyNIrX2+jwwjZo6\nFPGbyB6ph01YcH9cgpRtnykl7uDYTMCMlDNeOsaOFytK8khbdCm8YutGRxik\n4Eu6+FkmRHwICr+7liam/RimLOuJe1dGDTPuXPQd+jdAiCqQG3LpTJq5D64i\nPQqK5Tn3KtwyaPrkBeTBWZcJmhAfqjgyOCfFGEDcnMtUf5o4+/Ap3P9mtXOt\n3Wsrb1rv3vWpxwKVSxuZBGQKoV/qu+vMJXUX6v+vqlgC9tbUr6FWjUVo1tlc\nMYICIMu+UAUxtxkWYLeoQtLR9oJ8Baa4PN+/6dcG24YjkSh+2qaA9/oGIjO+\nxCyp+emlQxwKvDj8pekhYtqTFKVbAGDW6kmaOYqnyvlFrd3EZY24keFR89KE\nI3MhyRMY7UWXDAIIooyBJFUzepH6ImfeIqLrvnE8vuoNsTgEGJ5bV4G48SRA\nTHvrYCEwkmPAzMEW0Fti52OCuiIKW3ad4SKqs1K16qAoT4sdcut4fS1LENMl\nTWl4ElYq8V2U9Y0vy6DPc2FD17Wk2INj3CtMVMQP7nH5Dey9pXtGfO91KaKZ\nTIYie05xdx8TEGyQhGD7Y4IfJohxzBA6eGfjl+44VhX0Unhh+FGEYVV91s78\ny3P1\r\n=cAE+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxVBgwNb9MmFjzxDkpW0Qf9qDCc2YjQ2R03jr0Cr+X0QIgFzCVNDFIdZlQvGzEyUtt7OCY61FCEYXAMGXIfHOltbo="}]},"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.3.3_1620893797607_0.7640819727710126"},"_hasShrinkwrap":false},"5.3.4":{"name":"babel-plugin-nornj-in-jsx","version":"5.3.4","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.3.4","nornj-react":"^5.3.4"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"20089e300df5f9b8442bf16fa47b60bb96c19f94","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.3.4","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.18.3/node@v12.18.3+x64 (win32)","dist":{"integrity":"sha512-pcHsgwrfNtvGx54EdsyUgd0BM4YxSQVJLwFduIb3TmdMCwZLHRDevMjMC+YDOsV1skytAejGImNCImCYxM7M5A==","shasum":"707170132aec22814c647322ea7e4bea2153eb59","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.3.4.tgz","fileCount":12,"unpackedSize":49041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgp4KtCRA9TVsSAnZWagAAJNUP/icr4ozT6pPQBomDchjH\n7+78B+rStKDfZcSXgkcE7I/JHNdUjavcQ/xcjaOEwMotajwhNwfEgQIOICa2\n2Ky1WX1u+4BIKcENWJzFcaeEW9U54iFy+LtXp+/IbU0O5NniyHfCfOj7hxev\nrPLDLHNv5kTClV0opiQwkfdCX5QHPurPWiv2/jexXnxzGqHowS/XAF+mGRxT\nsWan88kwvjLLvsBZ9QCfJvH3ma/WZmeKD0RF722X2NFeCsw50Al3V+fUa7Up\nbod6wHjgjEgM5/lCnC/UX5mhIJHIcgOZ7+FDnxSeUs3npTHC+bS0O26/bBVC\n597g3/WsAK19ARmQmOArDjJP4Fynd7Vidfa+Lv1K8E6Q+C8uOpdOKaV8sNTi\nWsaZv1uG84hBdWBif47LDFl3nzGN2rZ2+BrlKNld2k6AamNsDtOzfM9CSrtE\nJSiNEO9Kw2NBbyZL3CybawvFlKhr54vvmQaw2X5kBCXhm0xTkkTNLysNko8O\n3i4H1srnfEDrblIxkksrigu7tZ0u6Kw83EDzPJnQIkpzuFqTRgCguWhcmytG\n1DxJl1hKlw81MAtKamWvpoEx9C7j22Bc3aZXK9H/k7FVodCrI87/IZGglmqV\ncLJj7y2sOysve5PEdQ7pAlZvEqeX0k3I1LLE4cyzh2iJTDH7sSRc2LxaNhF5\nWNxx\r\n=vBP4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDoFnpX4vcDYSr7vKIHIfco/LitaY/GsfY0onSmDIYrCQIgXV/fJaHIK/fcHAGy7FCjHM3otat/LcrERa4/+B3npiU="}]},"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.3.4_1621590700916_0.7552953688948623"},"_hasShrinkwrap":false},"5.3.5":{"name":"babel-plugin-nornj-in-jsx","version":"5.3.5","description":"Make the NornJ work gracefully in the JSX environment","author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"main":"src/index.js","repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"license":"MIT","scripts":{"test":"mocha test/index.js","cover":"istanbul cover -x \"**/test/**\" ../../node_modules/mocha/bin/_mocha test/index.js","ci":"yarn run cover && cat coverage/lcov.info | ../../node_modules/coveralls/bin/coveralls.js"},"dependencies":{"@babel/core":"^7.1.2","nornj":"^5.3.5","nornj-react":"^5.3.5"},"devDependencies":{"@babel/plugin-proposal-object-rest-spread":"^7.4.0","chai":"^3.5.0","chai-spies":"^0.7.1","coveralls":"^2.11.6","istanbul":"^0.4.1","mocha":"^3.0.2","styled-jsx":"^2.2.7"},"gitHead":"0249d4a4b8d2006e510fb8e94ae68406526ed2b1","homepage":"https://github.com/joe-sky/nornj#readme","_id":"babel-plugin-nornj-in-jsx@5.3.5","_nodeVersion":"14.19.0","_npmVersion":"lerna/3.18.3/node@v14.19.0+x64 (win32)","dist":{"integrity":"sha512-CP/grTPDqe85NnxhgLD2IPWK2ESyFptIHS9kxxPex4HR6JwAnkJImKJ/SsZygoIAkTM4uOZA7oZyWESnuaI9MA==","shasum":"1d711a8d218951bdb7abfe714b8afd5b81277763","tarball":"https://registry.npmjs.org/babel-plugin-nornj-in-jsx/-/babel-plugin-nornj-in-jsx-5.3.5.tgz","fileCount":12,"unpackedSize":49257,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDSDmgLSMo9G/U86lUubeB+6vHRR1cXM2FzFmLJiEAJUAiBqt48Ou6kJnj5tBEgkGZEWY8JVCfhP63SXDegeWh8diw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjDxKnACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpfDA/8CWaO5pPr7EP6PJFCdVujxOPlNl8Fz4rdiFOd3UClvAMFi9cH\r\n+7HxdNkalvSnAMxC0hjN2Wor/nePhz0Jgbu4JM4rIilFVJa1T+CwcO3Y70ps\r\no6fHIbV1I9OM/GP4aHQgPJg4lDjGjzZBUMHqsdO3XakTtqZCM3m3KeIlHAK1\r\nfZR8m+QN1t++idm4pvQRqgKrFNQFMZkKrg2oUOpMzEqscCWyuF3zChlBT9qG\r\ncQvHLM/VOj5W2SCMZJ8rMOzF1EPW6OTX8p8fqf0PWH5csuRTNPFmdYf8pZId\r\nBoMySEMDUSPeDuYETDJ+gcIadHfGzegu0MHjNRD5kUYlfDV8yP5oECAa8ECj\r\n0fDqVPgk0davvX3sxo/SobSAGhkYCp6FP4ls1YvGKH1h0LNoi/Fng2GqpSb0\r\nLmdiECG4vHM7fmtHNO+G4uMAgnKg3GLdh9QZNKHs0CIxYyxmhME5sJrkLMCH\r\nToaJyf7TfZQnSauP/f5G++zHS4uaccc4ECUQiRzCINV7JGg+qvRjwKEzfTZT\r\nFO2xFoCSinntuNtuIBSF5hn7lR4klYfx0r7a8uTyYmdVjcni0M1F4WC0vL9U\r\ns6boLiWdKHj/CjnlCQdAaDRxGHrVyGUCm4fQEuRA2M5ZyInL8I1PP42xQXLJ\r\n+yv81CWXHD7/1P2Iex7JD39+UBIEYCl0ZCk=\r\n=Gmzc\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joe_sky","email":"hitomi_doax@sina.com"},"directories":{},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/babel-plugin-nornj-in-jsx_5.3.5_1661932199552_0.2603177838221391"},"_hasShrinkwrap":false}},"time":{"created":"2018-04-18T04:48:57.461Z","0.4.2-alpha.1":"2018-04-18T04:48:57.536Z","modified":"2022-08-31T07:49:59.782Z","0.4.2-alpha.2":"2018-04-18T07:18:08.804Z","0.4.2-alpha.3":"2018-05-17T06:51:23.195Z","0.4.2-alpha.4":"2018-05-22T08:39:17.954Z","0.4.2-alpha.5":"2018-05-22T08:47:50.076Z","0.4.2-alpha.6":"2018-05-22T08:54:31.610Z","0.4.2-alpha.7":"2018-05-22T09:14:32.311Z","0.4.2-alpha.8":"2018-05-23T02:18:46.487Z","0.4.2":"2018-05-24T07:25:42.148Z","0.4.3":"2018-08-01T10:33:37.600Z","0.4.4":"2018-08-02T04:39:55.635Z","0.4.5":"2018-08-10T13:09:11.096Z","0.4.6":"2018-08-23T06:52:17.211Z","0.4.7":"2018-09-05T10:04:59.690Z","0.4.8":"2018-09-21T04:44:36.933Z","0.4.9":"2018-10-17T08:24:59.774Z","0.4.10":"2018-10-17T09:41:25.432Z","0.4.11":"2018-12-12T09:28:08.655Z","0.4.12":"2018-12-12T09:52:43.900Z","0.4.13":"2018-12-14T09:47:29.386Z","0.4.14":"2018-12-20T08:50:37.144Z","0.4.15":"2018-12-29T10:22:53.322Z","5.0.0-alpha.1":"2019-02-12T04:26:17.654Z","5.0.0-alpha.2":"2019-02-12T04:30:23.418Z","5.0.0-alpha.3":"2019-02-12T06:53:01.782Z","5.0.0-alpha.4":"2019-02-12T07:46:31.368Z","5.0.0-alpha.5":"2019-02-27T09:09:49.577Z","5.0.0-alpha.6":"2019-02-28T10:09:10.076Z","5.0.0-alpha.7":"2019-03-08T13:00:40.868Z","5.0.0-beta.1":"2019-03-13T11:07:16.936Z","5.0.0-beta.2":"2019-03-14T07:29:25.778Z","5.0.0-beta.3":"2019-03-14T10:16:37.458Z","5.0.0-beta.4":"2019-03-27T10:38:34.631Z","5.0.0-beta.5":"2019-04-01T03:52:55.601Z","5.0.0-beta.6":"2019-04-01T03:54:12.105Z","5.0.0-beta.7":"2019-04-01T04:28:45.248Z","5.0.0-beta.8":"2019-04-01T04:41:09.084Z","5.0.0-rc.1":"2019-04-09T02:39:16.516Z","5.0.0-rc.2":"2019-04-09T03:05:53.510Z","5.0.0-rc.3":"2019-04-09T03:25:16.259Z","5.0.0-rc.4":"2019-04-09T03:35:26.442Z","5.0.0-rc.5":"2019-04-10T12:00:59.442Z","5.0.0-rc.6":"2019-04-14T11:34:50.259Z","5.0.0-rc.7":"2019-04-14T12:05:54.173Z","5.0.0-rc.8":"2019-04-22T03:03:18.291Z","5.0.0-rc.9":"2019-05-05T04:08:01.070Z","5.0.0-rc.10":"2019-05-05T10:28:09.536Z","5.0.0-rc.11":"2019-05-06T10:40:53.801Z","5.0.0-rc.12":"2019-05-07T07:31:16.158Z","5.0.0-rc.13":"2019-05-08T03:16:05.448Z","5.0.0-rc.14":"2019-05-08T04:32:46.274Z","5.0.0-rc.15":"2019-05-09T03:38:37.491Z","5.0.0-rc.16":"2019-05-09T04:47:41.979Z","5.0.0-rc.17":"2019-05-09T06:46:34.282Z","5.0.0-rc.18":"2019-05-14T08:52:51.943Z","5.0.0-rc.19":"2019-05-14T12:07:52.343Z","5.0.0-rc.20":"2019-05-14T12:20:17.182Z","5.0.0-rc.21":"2019-05-20T08:54:54.806Z","5.0.0-rc.22":"2019-05-22T06:29:05.037Z","5.0.0-rc.23":"2019-05-23T07:39:18.974Z","5.0.0-rc.24":"2019-06-05T13:02:43.456Z","5.0.0-rc.25":"2019-06-14T07:05:37.724Z","5.0.0-rc.26":"2019-06-23T14:04:58.037Z","5.0.0-rc.27":"2019-07-03T10:04:30.021Z","5.0.0-rc.28":"2019-07-26T05:32:27.151Z","5.0.0-rc.29":"2019-08-20T12:20:25.853Z","5.0.0-rc.30":"2019-08-21T08:52:27.788Z","5.0.0-rc.31":"2019-08-22T11:31:16.264Z","5.0.0-rc.32":"2019-08-22T11:58:43.642Z","5.0.0-rc.33":"2019-09-06T09:53:33.050Z","5.0.0-rc.34":"2019-09-12T07:19:48.607Z","5.0.0-rc.35":"2019-09-16T03:58:33.033Z","5.0.0-rc.36":"2019-10-17T03:25:07.536Z","5.0.0-rc.37":"2019-10-23T04:50:15.476Z","5.0.0-rc.38":"2019-10-23T06:51:58.881Z","5.0.0-rc.39":"2019-10-29T08:21:15.872Z","5.0.0-rc.40":"2019-10-30T04:47:16.967Z","5.0.0-rc.41":"2019-10-30T09:04:13.820Z","5.0.0-rc.42":"2019-11-08T10:32:33.827Z","5.0.0-rc.43":"2019-11-08T12:33:09.768Z","5.0.0-rc.44":"2019-11-11T08:41:14.071Z","5.0.0-rc.45":"2019-11-12T11:06:15.408Z","5.0.0-rc-46":"2019-11-13T12:07:46.587Z","5.0.0-rc.47":"2019-11-15T08:47:24.948Z","5.0.0-rc.48":"2019-11-19T11:15:55.315Z","5.0.0-rc.49":"2019-11-20T11:20:25.901Z","5.0.0-rc.50":"2019-11-22T11:50:51.705Z","5.0.0-rc.51":"2019-11-26T11:35:05.665Z","5.0.0":"2019-12-03T08:40:42.089Z","5.0.1":"2019-12-04T12:09:30.637Z","5.0.2":"2019-12-06T03:41:03.319Z","5.0.3":"2019-12-07T15:02:08.170Z","5.0.4":"2019-12-09T07:10:26.522Z","5.0.5":"2019-12-09T13:00:26.973Z","5.0.6":"2019-12-17T11:10:11.320Z","5.0.7":"2019-12-31T10:26:53.792Z","5.1.0":"2020-01-10T11:00:14.820Z","5.1.1":"2020-02-05T10:48:39.059Z","5.2.0-beta.1":"2020-03-18T17:38:37.894Z","5.2.0-beta.2":"2020-03-22T15:55:29.179Z","5.2.0-beta.3":"2020-04-03T11:51:07.715Z","5.2.0-beta.4":"2020-04-10T12:47:37.011Z","5.2.0-beta.5":"2020-04-12T14:06:06.722Z","5.2.0-rc.1":"2020-05-27T04:20:11.048Z","5.2.0-rc.2":"2020-06-01T08:36:50.891Z","5.2.0-rc.3":"2020-06-01T09:27:50.347Z","5.2.0-rc.4":"2020-06-08T09:08:44.836Z","5.2.0-rc.5":"2020-06-22T08:15:25.369Z","5.2.0-rc.6":"2020-07-01T12:00:05.189Z","5.2.0-rc.7":"2020-07-01T12:45:14.259Z","5.2.0-rc.8":"2020-07-01T13:06:33.912Z","5.2.0-rc.9":"2020-07-07T12:13:41.012Z","5.2.0":"2020-07-08T12:52:00.407Z","5.2.1":"2020-07-09T12:02:27.321Z","5.2.2":"2020-07-20T09:27:54.912Z","5.2.3":"2020-07-20T09:49:04.301Z","5.2.4":"2020-07-20T10:59:21.909Z","5.2.5":"2020-08-06T08:08:39.135Z","5.2.6":"2020-09-16T08:35:16.541Z","5.2.7":"2020-09-16T08:59:06.941Z","5.2.8":"2020-09-16T10:40:51.273Z","5.3.0":"2020-12-30T12:14:45.027Z","5.3.1":"2021-02-04T09:31:24.742Z","5.3.2":"2021-02-07T07:23:44.889Z","5.3.3":"2021-05-13T08:16:37.844Z","5.3.4":"2021-05-21T09:51:41.088Z","5.3.5":"2022-08-31T07:49:59.709Z"},"maintainers":[{"name":"joe_sky","email":"hitomi_doax@sina.com"}],"description":"Make the NornJ work gracefully in the JSX environment","homepage":"https://github.com/joe-sky/nornj#readme","keywords":["react","jsx","nornj","if","else","for","each","loop","switch","babel"],"repository":{"type":"git","url":"git+https://github.com/joe-sky/nornj.git"},"author":{"name":"Joe_Sky","email":"hitomi_doax@sina.com"},"bugs":{"url":"https://github.com/joe-sky/nornj/issues"},"license":"MIT","readme":"<div align=\"center\">\r\n  <a href=\"https://joe-sky.github.io/nornj/\">\r\n    <img width=\"100\" src=\"https://joe-sky.github.io/nornj/images/logo.png\">\r\n  </a>\r\n  <a href=\"https://babeljs.io/\">\r\n    <img width=\"245\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\">\r\n  </a>\r\n  <div>\r\n    <img width=\"100\" height=\"100\" title=\"Babel Plugin\" src=\"https://michael-ciniawsky.github.io/postcss-load-plugins/logo.svg\">\r\n  </div>\r\n  <h1>Babel-Plugin-NornJ-in-jsx</h1>\r\n  <p>一个可支持自由扩展的JSX语法增强插件 :wink:</p>\r\n</div>\r\n\r\n[![NPM Version][npm-image]][npm-url]\r\n[![Coverage Status](https://coveralls.io/repos/github/joe-sky/nornj/badge.svg?branch=master)](https://coveralls.io/github/joe-sky/nornj?branch=master)\r\n[![NPM Downloads][downloads-image]][npm-url]\r\n\r\n`Babel-Plugin-NornJ-in-jsx`是一个能为 JSX 带来更多丰富语法的 Babel 插件，比如条件及循环语句：\r\n\r\n```js\r\nconst Button = () => {\r\n  return (\r\n    <div>\r\n      <for i={0} to={10}>\r\n        <if condition={i < 5}>\r\n          <i>less than 5</i>\r\n          <else>\r\n            <i>greater than 5</i>\r\n          </else>\r\n        </if>\r\n      </for>\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n以及类似 Vue、Angular 的指令：\r\n\r\n```js\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input type=\"button\" n-show={props.showBtn} />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n还有过滤器：\r\n\r\n```js\r\nconst Button = props => {\r\n  return <div>{n`${props.name} | upperFirst`}</div>;\r\n};\r\n```\r\n\r\n更重要的是，除了以上这些预置的语法，还支持像 Vue、Angular 那样自由扩展新的语法：\r\n\r\n```js\r\nimport nj from 'nornj';\r\nimport cn from 'classnames';\r\nnj.registerExtension('class', opts => cn(opts.value()));\r\n\r\nconst Button = props => {\r\n  return (\r\n    <div>\r\n      <input\r\n        type=\"button\"\r\n        n-class={{\r\n          className1: true,\r\n          className2: props.hasClassName2\r\n        }}\r\n      />\r\n    </div>\r\n  );\r\n};\r\n```\r\n\r\n## 为什么创建这个插件？\r\n\r\n在`React`项目开发中，原生的`JSX`语法并没有提供类似`Vue`的`v-if`、`v-for`、`v-show`等模板语法糖。当然，社区为`JSX`贡献了不少相关的插件，比如[jsx-control-statements](https://github.com/AlexGilleran/jsx-control-statements)。\r\n\r\n而`Babel-Plugin-NornJ-in-jsx`的设计灵感就来源于上述的`jsx-control-statements`。只不过，它比前者的功能要更加丰富得多；且可以支持扩展 :wink:。\r\n\r\n## License\r\n\r\nMIT\r\n\r\n[npm-image]: http://img.shields.io/npm/v/babel-plugin-nornj-in-jsx.svg\r\n[downloads-image]: http://img.shields.io/npm/dm/babel-plugin-nornj-in-jsx.svg\r\n[npm-url]: https://www.npmjs.org/package/babel-plugin-nornj-in-jsx\r\n","readmeFilename":"README.md"}