├── .eslintrc.yml ├── .gitignore ├── .prettierrc ├── README.md ├── package.json ├── renovate.json └── src ├── README.md ├── assets ├── code.png ├── icon.png ├── prism.html └── react-lottie.json ├── config.json ├── main.js ├── scripts ├── components │ ├── CodeView.js │ ├── CustomProfiler.js │ └── ExampleView.js ├── constants.js ├── examples │ ├── AnimateExample.js │ ├── BasicExample.js │ ├── CacheExample.js │ ├── HttpExample.js │ ├── InfiniteLoadingExample.js │ ├── JsxLiteralExample.js │ ├── LottieExample.js │ ├── SettingsExample.js │ ├── TodoExample.js │ ├── WebViewExample.js │ └── index.js ├── helper.js ├── index.js └── store.js └── strings ├── en.strings └── zh-Hans.strings /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | es6: true 4 | parser: babel-eslint 5 | extends: 6 | - eslint:recommended 7 | - plugin:react/recommended 8 | - plugin:jsbox/default 9 | plugins: 10 | - react 11 | - react-hooks 12 | globals: 13 | JSBox: writable 14 | '$image': readonly 15 | settings: 16 | react: 17 | version: detect 18 | rules: 19 | semi: 20 | - 2 21 | - never 22 | arrow-parens: 0 23 | global-require: 0 24 | no-underscore-dangle: 0 25 | no-param-reassign: 0 26 | import/prefer-default-export: 0 27 | react/prop-types: 'off' 28 | react-hooks/rules-of-hooks: error 29 | react-hooks/exhaustive-deps: warn 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | yarn.lock 8 | .DS_Store 9 | .cache 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (https://nodejs.org/api/addons.html) 36 | build/Release 37 | dist 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | # next.js build output 65 | .next 66 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "semi": false, 5 | "singleQuote": true, 6 | "arrowParens": "avoid", 7 | "bracketSpacing": true, 8 | "trailingComma": "none" 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-jsbox-example 2 | 3 | ## Usage 4 | 5 | ### Install 6 | 7 | ```sh 8 | npm install 9 | ``` 10 | 11 | ### Dev 12 | 13 | Requirements: jsbox-cli. code sync and build .box file 14 | usage: https://www.npmjs.com/package/jsbox-cli 15 | 16 | ```sh 17 | npx jsbox set "your JSBox host ip" 18 | 19 | npm run dev 20 | ``` 21 | 22 | ### Build 23 | 24 | ```sh 25 | npm run build 26 | ``` 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-jsbox-example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dist/main.js", 6 | "scripts": { 7 | "dev": "run-p bundle watch", 8 | "watch": "jsbox watch dist", 9 | "bundle": "parcel watch src/main.js --no-source-maps --no-hmr", 10 | "clean": "rimraf .cache", 11 | "build": "npm run clean && parcel build src/main.js --no-source-maps", 12 | "build:box": "jsbox build dist", 13 | "lint": "eslint --fix src/**/*.js", 14 | "format": "prettier --ignore-path .gitignore --single-quote --write src/**/*.{js,md}", 15 | "husky-run": "npm run format && npm run lint && git add .", 16 | "postinstall": "npm run build" 17 | }, 18 | "keywords": [], 19 | "author": "", 20 | "license": "ISC", 21 | "browserslist": [ 22 | "iOS 12" 23 | ], 24 | "babel": { 25 | "presets": [ 26 | [ 27 | "@babel/preset-env", 28 | { 29 | "targets": "iOS 12" 30 | } 31 | ], 32 | "@babel/preset-react" 33 | ] 34 | }, 35 | "url-loader": { 36 | "exts": [ 37 | "jpg", 38 | "jpeg", 39 | "png", 40 | "gif" 41 | ], 42 | "limit": 10240 43 | }, 44 | "resolutions": { 45 | "@babel/preset-env": "7.13.8" 46 | }, 47 | "devDependencies": { 48 | "@babel/cli": "7.14.5", 49 | "@babel/core": "7.14.5", 50 | "@babel/plugin-transform-runtime": "7.14.5", 51 | "@babel/preset-env": "7.14.5", 52 | "@babel/preset-react": "7.14.5", 53 | "@babel/runtime": "7.14.5", 54 | "babel-eslint": "10.1.0", 55 | "eslint": "7.28.0", 56 | "eslint-plugin-jsbox": "0.1.1", 57 | "eslint-plugin-react": "7.24.0", 58 | "eslint-plugin-react-hooks": "4.2.0", 59 | "husky": "6.0.0", 60 | "jsbox-cli": "1.2.1", 61 | "npm-run-all": "4.1.5", 62 | "parcel": "1.12.4", 63 | "parcel-plugin-bundle-visualiser": "1.2.0", 64 | "parcel-plugin-nuke-dist": "1.0.1", 65 | "parcel-plugin-static-files-copy": "2.6.0", 66 | "parcel-plugin-url-loader": "1.3.1", 67 | "prettier": "2.3.1", 68 | "rimraf": "3.0.2" 69 | }, 70 | "dependencies": { 71 | "core-js": "^3.14.0", 72 | "htm": "^3.0.4", 73 | "immer": "^9.0.3", 74 | "invert-color": "^2.0.0", 75 | "lodash-es": "^4.17.21", 76 | "pupa": "github:nicify/pupa#master", 77 | "react": "^17.0.2", 78 | "react-jsbox": "^1.3.2", 79 | "swr": "^0.5.6", 80 | "use-immer": "^0.5.2", 81 | "use-simple-store": "^1.4.1" 82 | }, 83 | "staticFiles": { 84 | "staticPath": [ 85 | "src" 86 | ], 87 | "watcherGlob": "^**" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "automerge": true, 4 | "major": { 5 | "automerge": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rel1cx/react-jsbox-example/5bdc0e740110d9d802a61e2bf0dbc7902e467373/src/README.md -------------------------------------------------------------------------------- /src/assets/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rel1cx/react-jsbox-example/5bdc0e740110d9d802a61e2bf0dbc7902e467373/src/assets/code.png -------------------------------------------------------------------------------- /src/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rel1cx/react-jsbox-example/5bdc0e740110d9d802a61e2bf0dbc7902e467373/src/assets/icon.png -------------------------------------------------------------------------------- /src/assets/prism.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | Code 14 | 35 | 36 | 37 | 38 |
<%=code%>
42 | 43 | 44 | 45 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/assets/react-lottie.json: -------------------------------------------------------------------------------- 1 | {"v":"4.6.3","fr":29.9700012207031,"ip":0,"op":141.000005743048,"w":800,"h":800,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"center_circle","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[401,389,0]},"a":{"a":0,"k":[-13.063,-22.86,0]},"s":{"a":0,"k":[119.72,119.72,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[77.344,77.344]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0.898039,0.223529,0.207843,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0.0196078,0.6470588,0.8196078,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[-14.328,-25.328],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":24,"s":[0,0],"e":[160,160]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":45,"s":[160,160],"e":[70,70]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":61,"s":[70,70],"e":[130,130]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":73,"s":[130,130],"e":[80,80]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":84,"s":[80,80],"e":[110,110]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":98,"s":[110,110],"e":[100,100]},{"t":116.000004724777}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900.000036657751,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"circle3","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-120.543},"p":{"a":0,"k":[406,375,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[104.627,108.478,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[497.445,195.844]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p833_1_0p333_0"],"t":64,"s":[100],"e":[0]},{"t":110.000004480392}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0.333]},"n":["0p833_0p833_0p333_0p333"],"t":64,"s":[100],"e":[100]},{"t":110.000004480392}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.69],"y":[3.268]},"o":{"x":[0.294],"y":[0]},"n":["0p69_3p268_0p294_0"],"t":64,"s":[1886.781],"e":[1765.781]},{"t":115.000004684046}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"},{"ty":"st","c":{"a":0,"k":[0.0196078,0.6470588,0.8196078,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[0.936]},"o":{"x":[0.333],"y":[0]},"n":["0p667_0p936_0p333_0"],"t":55,"s":[0],"e":[23.039]},{"i":{"x":[0.667],"y":[1.13]},"o":{"x":[0.333],"y":[-0.043]},"n":["0p667_1p13_0p333_-0p043"],"t":74,"s":[23.039],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0.158]},"n":["0p667_1_0p333_0p158"],"t":85,"s":[3],"e":[24]},{"t":99.0000040323527}]},"lc":2,"lj":2,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[-6.277,-10.078],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[89.823,86.077],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900.000036657751,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"circle2","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-59.94},"p":{"a":0,"k":[413,385,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[104.627,108.478,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[497.445,195.844]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":46,"s":[100],"e":[84.162]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[-0.084]},"n":["0p833_1_0p333_-0p084"],"t":73,"s":[84.162],"e":[100]},{"t":104.000004236007}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.324],"y":[0]},"n":["0p833_1_0p324_0"],"t":46,"s":[100],"e":[0]},{"t":104.000004236007}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[0.953]},"o":{"x":[0.327],"y":[0]},"n":["0p667_0p953_0p327_0"],"t":46,"s":[50],"e":[2101.915]},{"t":105.000004276738}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"},{"ty":"st","c":{"a":0,"k":[0.0196078,0.6470588,0.8196078,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[0.91]},"o":{"x":[0.333],"y":[0]},"n":["0p667_0p91_0p333_0"],"t":60,"s":[0],"e":[13]},{"i":{"x":[0.667],"y":[1.258]},"o":{"x":[0.333],"y":[-0.085]},"n":["0p667_1p258_0p333_-0p085"],"t":75,"s":[13],"e":[2]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0.183]},"n":["0p667_1_0p333_0p183"],"t":87,"s":[2],"e":[24]},{"t":104.000004236007}]},"lc":2,"lj":2,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[-7.277,-10.078],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[89.823,86.077],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900.000036657751,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"circle1","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[407,397,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[104.627,108.478,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[497.445,195.844]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[100],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":53,"s":[100],"e":[55.162]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0.01]},"n":["0p833_1_0p333_0p01"],"t":92,"s":[55.162],"e":[0]},{"t":105.000004276738}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0.333]},"n":["0p833_0p833_0p333_0p333"],"t":53,"s":[100],"e":[100]},{"t":103.000004195276}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_1_0p167_0p167"],"t":0,"s":[100],"e":[50]},{"i":{"x":[0.714],"y":[0.721]},"o":{"x":[0.303],"y":[0]},"n":["0p714_0p721_0p303_0"],"t":53,"s":[50],"e":[958.781]},{"t":104.000004236007}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"},{"ty":"st","c":{"a":0,"k":[0.0196078,0.6470588,0.8196078,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[0.908]},"o":{"x":[0.333],"y":[0]},"n":["0p667_0p908_0p333_0"],"t":52,"s":[0],"e":[16.039]},{"i":{"x":[0.667],"y":[1.259]},"o":{"x":[0.333],"y":[-0.085]},"n":["0p667_1p259_0p333_-0p085"],"t":71,"s":[16.039],"e":[6]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0.184]},"n":["0p667_1_0p333_0p184"],"t":82,"s":[6],"e":[24]},{"t":96.0000039101602}]},"lc":2,"lj":2,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[-7.277,-10.078],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[89.823,86.077],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900.000036657751,"st":0,"bm":0,"sr":1}]} -------------------------------------------------------------------------------- /src/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "react-jsbox-example", 4 | "url": "https://github.com/Nicify/react-jsbox-example", 5 | "version": "1.0.0", 6 | "author": "Eva1ent", 7 | "website": "https://github.com/Nicify/react-jsbox-example", 8 | "types": 1 9 | }, 10 | "settings": { 11 | "theme": "auto", 12 | "minSDKVer": "1.0.0", 13 | "minOSVer": "12.0.0", 14 | "idleTimerDisabled": false, 15 | "autoKeyboardEnabled": false, 16 | "keyboardToolbarEnabled": true, 17 | "rotateDisabled": true 18 | }, 19 | "widget": { 20 | "height": 0, 21 | "staticSize": false, 22 | "tintColor": "", 23 | "iconColor": "" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | global.navigator = {} 2 | require('./scripts/index') 3 | -------------------------------------------------------------------------------- /src/scripts/components/CodeView.js: -------------------------------------------------------------------------------- 1 | import React, { memo, useMemo } from 'react' 2 | import pupa from 'pupa' 3 | 4 | const HLTemplate = $file.read('assets/prism.html').string 5 | 6 | function CodeView({ content, ...rest }) { 7 | const html = useMemo(() => pupa(HLTemplate, { code: content }), [content]) 8 | 9 | return 10 | } 11 | 12 | export default memo(CodeView) 13 | -------------------------------------------------------------------------------- /src/scripts/components/CustomProfiler.js: -------------------------------------------------------------------------------- 1 | import React, { Profiler } from 'react' 2 | 3 | export default function CustomProfiler({ enable = false, children, ...rest }) { 4 | if (!enable) { 5 | return children 6 | } 7 | return {children} 8 | } 9 | -------------------------------------------------------------------------------- /src/scripts/components/ExampleView.js: -------------------------------------------------------------------------------- 1 | import React, { memo, useState } from 'react' 2 | import { codeIcon } from '../constants' 3 | 4 | const ExampleView = ({ frame, demo, code }) => { 5 | const { width } = frame 6 | const [showCode, setShowCode] = useState(false) 7 | 8 | return ( 9 | <> 10 | {showCode ? code : demo} 11 |