├── .gitignore
├── README.md
├── generic-jsx-babel-plugin
├── generic-jsx-babel-plugin.js
├── package-lock.json
└── package.json
├── generic-jsx-examples
├── binary-tree.js
├── immutable-map.js
├── package.json
├── react.js
└── reduce.js
└── generic-jsx
├── generic-jsx.js
├── package-lock.json
├── package.json
└── runkitExample.js
/.gitignore:
--------------------------------------------------------------------------------
1 | lithograph/test-worker/test-environment-preload.bundle.js
2 |
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
10 | # Apple
11 | .DS_Store
12 |
13 | #petrified
14 | _site
15 |
16 | # Runtime data
17 | pids
18 | *.pid
19 | *.seed
20 | *.pid.lock
21 |
22 | # Directory for instrumented libs generated by jscoverage/JSCover
23 | lib-cov
24 |
25 | # Coverage directory used by tools like istanbul
26 | coverage
27 |
28 | # nyc test coverage
29 | .nyc_output
30 |
31 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
32 | .grunt
33 |
34 | # Bower dependency directory (https://bower.io/)
35 | bower_components
36 |
37 | # node-waf configuration
38 | .lock-wscript
39 |
40 | # Compiled binary addons (https://nodejs.org/api/addons.html)
41 | build/Release
42 |
43 | # Dependency directories
44 | node_modules/
45 | jspm_packages/
46 |
47 | # Typescript v1 declaration files
48 | typings/
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Optional REPL history
57 | .node_repl_history
58 |
59 | # Output of 'npm pack'
60 | *.tgz
61 |
62 | # Yarn Integrity file
63 | .yarn-integrity
64 |
65 | # dotenv environment variables file
66 | .env
67 |
68 | # next.js build output
69 | .next
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | You can find a full explanation of the ideas behind this [here](http://tolmasky.com/2016/03/24/generalizing-jsx/).
3 |
4 | Or, try it on [RunKit](https://runkit.com/npm/generic-jsx)!
5 |
6 | # Generic JSX
7 |
8 | This is a version of JSX for general purpose programming. Why would you want that? Well, it gives
9 | us the ability to have curried named parameters in JavaScript.
10 |
11 | # How Do I use It?
12 |
13 | If you are using Babel, then all you should need to do is the following:
14 |
15 | ```JavaScript
16 | /* @jsx curry(_=>eval(_)) */
17 | var { curry } = require("generic-jsx");
18 | ```
19 |
20 | Now you'll be able make functions with named parameters that you can curry:
21 |
22 | ```JavaScript
23 | var fs = require("fs");
24 | var readFileSync = ({ name, encoding }) => fs.readFileSync(name, encoding);
25 |
26 | // ...
27 | var readString = ;
28 |
29 | ();
30 | ```
31 |
32 | Or, use with data structures!
33 |
34 | ```JavaScript
35 | /* @jsx (curry(_=>eval(_))) */
36 | var { curry, from } = require("generic-jsx");
37 | var BinaryTree = require("generic-jsx/binary-tree");
38 |
39 | // This represents 5 / ( 4 + 6)
40 |
41 |
42 |
43 |
44 |
45 |
46 | ()
47 | ```
48 |
49 |
--------------------------------------------------------------------------------
/generic-jsx-babel-plugin/generic-jsx-babel-plugin.js:
--------------------------------------------------------------------------------
1 | const fail = message => { throw Error(message) };
2 |
3 | const toBoundAttributes = (t, attributes, children) =>
4 | t.ObjectExpression(attributes
5 | .map(JSXAttributeToObjectProperty(t)));
6 |
7 | const toChildrenArray = (t, children) =>
8 | t.ArrayExpression(children
9 | .map(child => toChildValue(t, child))
10 | .filter(child => !t.isJSXEmptyExpression(child)));
11 |
12 | const toExpression = (t, node) =>
13 | t.isJSXIdentifier(node) ?
14 | t.Identifier(node.name) :
15 | t.isJSXMemberExpression(node) ?
16 | t.MemberExpression(
17 | toExpression(t, node.object),
18 | toExpression(t, node.property)) :
19 | t.isJSXExpressionContainer(node) ?
20 | node.expression :
21 | fail(`Unexpected ${node.type} in JSX element`);
22 |
23 | const toChildValue = (t, child) =>
24 | t.isJSXText(child) ? t.StringLiteral(child.extra.raw) :
25 | t.isJSXExpressionContainer(child) ? child.expression :
26 | child;
27 |
28 | const JSXAttributeToObjectProperty = t => node =>
29 | t.isJSXSpreadAttribute(node) ?
30 | t.SpreadElement(node.argument) :
31 | t.ObjectProperty(
32 | t.Identifier(node.name.name),
33 | toAttributeValue(t, node.value));
34 |
35 | const toAttributeValue = (t, value) =>
36 | value === null ? t.BooleanLiteral(true) :
37 | t.isStringLiteral(value) ? value :
38 | t.isJSXExpressionContainer(value) ? value.expression :
39 | fail(`Unexpected ${value.type} in JSX element`);
40 |
41 | const toBoundFunction = (t, bind, { openingElement, children }) =>
42 | t.CallExpression((bind.used = true) && bind,
43 | [
44 | toExpression(t, openingElement.name),
45 | toBoundAttributes(t, openingElement.attributes, children),
46 | openingElement.selfClosing ?
47 | t.BooleanLiteral(false) :
48 | toChildrenArray(t, children)
49 | ]);
50 |
51 | const toImportStatement = (t, as, source) =>
52 | t.VariableDeclaration("const",
53 | [
54 | t.VariableDeclarator(
55 | as,
56 | t.MemberExpression(
57 | t.CallExpression(
58 | t.Identifier("require"),
59 | [t.StringLiteral(source)]),
60 | t.Identifier("bind"))),
61 | ]);
62 |
63 | const get = (state, name) =>
64 | state.get(`@generic-jsx/plugin-generic-jsx/${name}`);
65 | const set = (state, name, value) =>
66 | (state.set(`@generic-jsx/plugin-generic-jsx/${name}`, value), value);
67 |
68 | module.exports = ({ types: t }) =>
69 | ({
70 | manipulateOptions: (_, parserOptions) =>
71 | parserOptions.plugins.push("jsx"),
72 |
73 | visitor:
74 | {
75 | JSXElement: (path, state) => void(path
76 | .replaceWith(toBoundFunction(
77 | t,
78 | get(state, "bind-identifier"),
79 | path.node))),
80 |
81 | Program:
82 | {
83 | enter: (path, state) => void(
84 | !get(state, "bind-identifier") &&
85 | path.replaceWith(t.Program(
86 | [
87 | toImportStatement(
88 | t,
89 | set(
90 | state,
91 | "bind-identifier",
92 | path.scope.generateUidIdentifier("bind")),
93 | state.opts.importSource || "generic-jsx"),
94 | ...path.node.body
95 | ]))),
96 |
97 | exit: (path, state) => void(
98 | !get(state, "bind-identifier").used &&
99 | !get(state, "bind-removed") &&
100 | set(state, "bind-removed", true) &&
101 | path.replaceWith(t.Program(path.node.body.slice(1))))
102 | }
103 | }
104 | });
--------------------------------------------------------------------------------
/generic-jsx-babel-plugin/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@generic-jsx/babel-plugin",
3 | "version": "24.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "@generic-jsx/babel-plugin",
9 | "version": "24.0.0",
10 | "license": "MIT",
11 | "engines": {
12 | "node": ">=4.x.x"
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/generic-jsx-babel-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@generic-jsx/babel-plugin",
3 | "version": "24.0.0",
4 | "description": "Generalized JSX supporting curried named parameters. For full explanation see http://tolmasky.com/2016/03/24/generalizing-jsx",
5 | "main": "generic-jsx-babel-plugin.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/tolmasky/generic-jsx"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Francisco Ryan Tolmasky I (https://tolmasky.com/)",
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">=4.x.x"
17 | },
18 | "runkitExampleFilename": "runkitExample.js"
19 | }
20 |
--------------------------------------------------------------------------------
/generic-jsx-examples/binary-tree.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 |
4 | module.exports = function BinaryTree(value, ...[left, right])
5 | {
6 | if (!(this instanceof BinaryTree))
7 | return new BinaryTree(value, left, right);
8 |
9 | this.value = value;
10 |
11 | if (left)
12 | this.left = typeof left === "function" ? left() : left;
13 |
14 | if (right)
15 | this.right = typeof right === "function" ? right() : right;
16 | }
17 |
--------------------------------------------------------------------------------
/generic-jsx-examples/immutable-map.js:
--------------------------------------------------------------------------------
1 | const I = require("immutable");
2 |
3 |
4 | function Map(...entries)
5 | {
6 | return new I.Map(entries.map(child => child()));
7 | }
8 |
9 | Map.Entry = function(key, value)
10 | {
11 | return [key, value];
12 | }
13 |
14 | module.exports = Map;
15 |
--------------------------------------------------------------------------------
/generic-jsx-examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@generic-jsx/examples",
3 | "version": "24.0.0",
4 | "description": "Generalized JSX supporting curried named parameters. For full explanation see http://tolmasky.com/2016/03/24/generalizing-jsx",
5 | "main": "",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/tolmasky/generic-jsx"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Francisco Ryan Tolmasky I (https://tolmasky.com/)",
14 | "license": "MIT",
15 | "dependencies": {
16 | },
17 | "engines": {
18 | "node": ">=4.x.x"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/generic-jsx-examples/react.js:
--------------------------------------------------------------------------------
1 | const doublequote = string => `"${string.replace(/"/g, `\\"`)}"`;
2 | const CSSToString = style => doublequote(Object
3 | .entries(style)
4 | .map(([key, value]) => `${key}: ${value}`)
5 | .join("; "));
6 |
7 | exports.CSSToString = CSSToString;
8 |
9 | const element = name => (style, ...children) =>
10 | `<${name}${ style ? ` style = ${CSSToString(style)} ` : "" }>` +
11 | children.map(render).join("") +
12 | `${name}>`;
13 |
14 | exports.div = element("div");
15 | exports.h1 = element("h1");
16 | exports.p = element("p");
17 |
18 | const render = element =>
19 | typeof element === "string" ?
20 | element :
21 | render(element());
22 |
23 | exports.render = render;
24 |
--------------------------------------------------------------------------------
/generic-jsx-examples/reduce.js:
--------------------------------------------------------------------------------
1 | module.exports = function reduce(options)
2 | {
3 | var array = options.array;
4 | var initial = options.initial;
5 | var result = initial;
6 | var func = options.func;
7 |
8 | var index = 0;
9 | var count = array.length;
10 |
11 | for (; index < count; ++index)
12 | result = func(result, array[index]);
13 |
14 | return result;
15 | }
16 |
--------------------------------------------------------------------------------
/generic-jsx/generic-jsx.js:
--------------------------------------------------------------------------------
1 | const given = f => f();
2 |
3 | const
4 | {
5 | isArrayPattern,
6 | isAssignmentPattern,
7 | isIdentifier,
8 | isObjectPattern,
9 | isObjectProperty,
10 | isRestElement
11 | } = require("@babel/types");
12 | const { parseExpression } = require("@babel/parser");
13 |
14 | const ArrayIsArray = Array.isArray;
15 | const ArrayMerge = (...args) => ObjectAssign([], ...args);
16 |
17 | const FunctionPrototypeToString = Function.prototype.toString;
18 |
19 | const ObjectAssign = Object.assign;
20 | const ObjectGetOwnPropertyNames = Object.getOwnPropertyNames;
21 | const ObjectFromEntries = Object.fromEntries;
22 | const ObjectHasOwn = Object.hasOwn;
23 |
24 | const ObjectMerge = (...args) => ObjectAssign({ }, ...args);
25 | const ObjectDefinePropertyValue =
26 | (object, key, value) => Object.defineProperty(object, key, { value });
27 |
28 | const fNamed = (name, f) => ObjectDefinePropertyValue(f, "name", name);
29 |
30 | const isPrimitive = value =>
31 | value === null || typeof value !== "object" && typeof value !== "function";
32 |
33 | const fCached = f => given((
34 | cache = new WeakMap(),
35 | set = (arguments, value) => (cache.set(arguments[0], value), value),
36 | getset = (arguments, deferred) => cache.has(arguments[0]) ?
37 | cache.get(arguments[0]) :
38 | set(arguments, deferred(...arguments))) =>
39 | fNamed(`${f.name}-cached`, (...arguments) => isPrimitive(arguments[0]) ?
40 | f(arguments) :
41 | getset(arguments, f)));
42 |
43 | const BindingOfs = new WeakMap();
44 |
45 | const FunctionGetBindingOf = f => BindingOfs.get(f) || false;
46 | const FunctionGetBaseBindingOf = (f, fPrevious = f) =>
47 | f ? FunctionGetBaseBindingOf(FunctionGetBindingOf(f), f) : fPrevious;
48 |
49 | Function.getBindingOf = FunctionGetBindingOf;
50 |
51 | module.exports.getBindingOf = FunctionGetBindingOf;
52 |
53 | const fParseBindingOf = f => given((
54 | bindingOf = FunctionGetBindingOf(f)) =>
55 | bindingOf ? fParse(bindingOf) : fParseBindingOf(bindingOf));
56 |
57 | const fParse = fCached(f => given((
58 | fString = FunctionPrototypeToString.call(f),
59 | { type, params } = parseExpression(`(${fString})`),
60 | lastParameter = params.length > 0 && params[params.length - 1],
61 | restParameter = lastParameter && isRestElement(lastParameter) && lastParameter) =>
62 | ({
63 | stringified: fString,
64 | toBoundArguments: toToArguments(params),
65 | isArrowFunction: type === "ArrowFunctionExpression",
66 | length: restParameter ? params.length - 1 : params.length
67 | })));
68 |
69 | const MISSING = { missing: true };
70 |
71 | const toToArguments = node =>
72 | !node ?
73 | () => void(0) :
74 | ArrayIsArray(node) ?
75 | given((
76 | last = node.length >= 1 && node[node.length - 1],
77 | rest = last && isRestElement(last) && last,
78 | nonRest = rest ? node.slice(0, -1) : node,
79 | toRestArguments = rest ? toToArguments(rest) : () => [],
80 | toNonRestArguments = nonRest.map(toToArguments)) =>
81 | named => toNonRestArguments
82 | .map(f => f(named))
83 | .concat(toRestArguments(named, []))) :
84 | isArrayPattern(node) ?
85 | toToArguments(node.elements) :
86 | isObjectPattern(node) ?
87 | given((toArguments = toToArguments(node.properties)) =>
88 | named => ObjectAssign({}, ...toArguments(named))) :
89 | isObjectProperty(node) ?
90 | given((
91 | { key, value } = node,
92 | computedKey = isIdentifier(key) ? key.name : key.value,
93 | toArguments = toToArguments(node.value)) =>
94 | named => given((value = toArguments(named, MISSING)) =>
95 | value !== MISSING && ({ [computedKey]: value }))) :
96 | isIdentifier(node) ?
97 | given(({ name } = node) =>
98 | (named, fallback) =>
99 | ObjectHasOwn(named, name) ? named[name] : fallback) :
100 | isAssignmentPattern(node) ?
101 | toToArguments(node.left) :
102 | isRestElement(node) ?
103 | toToArguments(node.argument) :
104 | () => void(0);
105 |
106 | const RestEntries = Symbol("RestEntries");
107 |
108 | function bind(f, attributes, children)
109 | {
110 | if (children.length === 0 &&
111 | ObjectGetOwnPropertyNames(attributes).length === 0)
112 | return f;
113 |
114 | const baseBindingOf = FunctionGetBaseBindingOf(f);
115 | const
116 | {
117 | stringified,
118 | toBoundArguments,
119 | isArrowFunction,
120 | length
121 | } = fParse(baseBindingOf);
122 |
123 | const mergedAttributes = ObjectMerge(
124 | f.attributes,
125 | attributes,
126 | children &&
127 | {
128 | [RestEntries]: ObjectFromEntries(children
129 | .map((value, index) => [index + length, value]))
130 | });
131 |
132 | const toArguments = callArguments => ArrayMerge(
133 | toBoundArguments(mergedAttributes),
134 | mergedAttributes[RestEntries],
135 | callArguments);
136 |
137 | const fBound = isArrowFunction ?
138 | (...arguments) => baseBindingOf(...toArguments(arguments)) :
139 | function (...arguments)
140 | {
141 | return baseBindingOf.apply(this, toArguments(arguments));
142 | };
143 |
144 | BindingOfs.set(fBound, f);
145 |
146 | return ObjectAssign(fNamed(baseBindingOf.name, fBound),
147 | {
148 | attributes: mergedAttributes,
149 | toString() { return stringified; }
150 | });
151 | }
152 |
153 | module.exports.bind = bind;
154 |
155 | module.exports.JSXPragma = function JSXPragma(evalInScope)
156 | {
157 | return function JSXPragma(f, attributes, ...children)
158 | {
159 | return bind(
160 | typeof f === "string" ? evalInScope(f) : f,
161 | attributes,
162 | children);
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/generic-jsx/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generic-jsx",
3 | "version": "24.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "generic-jsx",
9 | "version": "24.0.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "@babel/parser": "^7.18.11",
13 | "@babel/types": "^7.18.10"
14 | },
15 | "engines": {
16 | "node": ">=4.x.x"
17 | }
18 | },
19 | "node_modules/@babel/helper-string-parser": {
20 | "version": "7.18.10",
21 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
22 | "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
23 | "engines": {
24 | "node": ">=6.9.0"
25 | }
26 | },
27 | "node_modules/@babel/helper-validator-identifier": {
28 | "version": "7.18.6",
29 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
30 | "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
31 | "engines": {
32 | "node": ">=6.9.0"
33 | }
34 | },
35 | "node_modules/@babel/parser": {
36 | "version": "7.18.11",
37 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
38 | "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==",
39 | "bin": {
40 | "parser": "bin/babel-parser.js"
41 | },
42 | "engines": {
43 | "node": ">=6.0.0"
44 | }
45 | },
46 | "node_modules/@babel/types": {
47 | "version": "7.18.10",
48 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
49 | "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
50 | "dependencies": {
51 | "@babel/helper-string-parser": "^7.18.10",
52 | "@babel/helper-validator-identifier": "^7.18.6",
53 | "to-fast-properties": "^2.0.0"
54 | },
55 | "engines": {
56 | "node": ">=6.9.0"
57 | }
58 | },
59 | "node_modules/to-fast-properties": {
60 | "version": "2.0.0",
61 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
62 | "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
63 | "engines": {
64 | "node": ">=4"
65 | }
66 | }
67 | },
68 | "dependencies": {
69 | "@babel/helper-string-parser": {
70 | "version": "7.18.10",
71 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
72 | "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw=="
73 | },
74 | "@babel/helper-validator-identifier": {
75 | "version": "7.18.6",
76 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
77 | "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
78 | },
79 | "@babel/parser": {
80 | "version": "7.18.11",
81 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
82 | "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ=="
83 | },
84 | "@babel/types": {
85 | "version": "7.18.10",
86 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
87 | "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
88 | "requires": {
89 | "@babel/helper-string-parser": "^7.18.10",
90 | "@babel/helper-validator-identifier": "^7.18.6",
91 | "to-fast-properties": "^2.0.0"
92 | }
93 | },
94 | "to-fast-properties": {
95 | "version": "2.0.0",
96 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
97 | "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/generic-jsx/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generic-jsx",
3 | "version": "24.0.0",
4 | "description": "Generalized JSX supporting curried named parameters. For full explanation see http://tolmasky.com/2016/03/24/generalizing-jsx",
5 | "main": "./generic-jsx",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/tolmasky/generic-jsx"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Francisco Ryan Tolmasky I (https://tolmasky.com/)",
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">=4.x.x"
17 | },
18 | "runkitExampleFilename": "runkitExample.js",
19 | "dependencies": {
20 | "@babel/parser": "^7.18.11",
21 | "@babel/types": "^7.18.10"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/generic-jsx/runkitExample.js:
--------------------------------------------------------------------------------
1 | /* @jsx (JSXPragma(_=>eval(_))) */
2 |
3 | const { JSXPragma } = require("generic-jsx");
4 | const BinaryTree = require("@generic-jsx/examples/binary-tree");
5 |
6 | // BinaryTree is an ES6 class that we can curry using JSX:
7 | const Division = ;
8 | const Addition = ;
9 | const Number = BinaryTree;
10 |
11 |
12 |
13 | { Number(5) }
14 |
15 | { Number(4) }
16 | { Number(6) }
17 |
18 | ()
19 |
--------------------------------------------------------------------------------