git.fiddlerwoaroof.com
Browse code

chore: reformat

fiddlerwoaroof authored on 07/07/2020 08:10:18
Showing 17 changed files
... ...
@@ -1,4 +1,4 @@
1 1
 {
2
-    "presets": ["@babel/env"],
3
-    "plugins": ["@babel/plugin-proposal-object-rest-spread"]
2
+  "presets": ["@babel/env"],
3
+  "plugins": ["@babel/plugin-proposal-object-rest-spread"]
4 4
 }
... ...
@@ -1,26 +1,26 @@
1 1
 {
2
-    "extends": [
3
-        "eslint:recommended",
4
-        "plugin:react/recommended"
5
-    ],
6
-    "env": {
7
-        "browser": true,
8
-        "node": true,
9
-        "jest": true,
10
-        "es6": true
11
-    },
12
-    "parserOptions": {
13
-        "ecmaVersion": 2018,
14
-        "sourceType": "module"
15
-    },
16
-    "rules": {
17
-        "no-unused-vars": ["error", {
18
-            "argsIgnorePattern": "(^[_][_]*.*$)|(^.$)"
19
-        }]
20
-    },
21
-    "settings": {
22
-        "react": {
23
-            "version": "detect"
24
-        }
2
+  "extends": ["eslint:recommended", "plugin:react/recommended"],
3
+  "env": {
4
+    "browser": true,
5
+    "node": true,
6
+    "jest": true,
7
+    "es6": true
8
+  },
9
+  "parserOptions": {
10
+    "ecmaVersion": 2018,
11
+    "sourceType": "module"
12
+  },
13
+  "rules": {
14
+    "no-unused-vars": [
15
+      "error",
16
+      {
17
+        "argsIgnorePattern": "(^[_][_]*.*$)|(^.$)"
18
+      }
19
+    ]
20
+  },
21
+  "settings": {
22
+    "react": {
23
+      "version": "detect"
25 24
     }
25
+  }
26 26
 }
... ...
@@ -1,21 +1,27 @@
1
-<!doctype html>
1
+<!DOCTYPE html>
2 2
 <html lang="en">
3
-    <head>
4
-        <meta charset="UTF-8"/>
5
-        <title>Document</title>
6
-        <style>
7
-            the-name {font-weight: bold}
8
-            the-address {font-style: italic}
9
-        </style>
10
-    </head>
11
-    <body>
12
-        <section class="root">
13
-            <the-name></the-name>
14
-            <the-address></the-address>
15
-        </section>
16
-        <script>var exports = {};</script>
17
-        <script src="./dist/genfuns.js"></script>
18
-        <script src="./dist/genfun_formatter.js"></script>
19
-        <script src="./dist/main.js"></script>
20
-    </body>
3
+  <head>
4
+    <meta charset="UTF-8" />
5
+    <title>Document</title>
6
+    <style>
7
+      the-name {
8
+        font-weight: bold;
9
+      }
10
+      the-address {
11
+        font-style: italic;
12
+      }
13
+    </style>
14
+  </head>
15
+  <body>
16
+    <section class="root">
17
+      <the-name></the-name>
18
+      <the-address></the-address>
19
+    </section>
20
+    <script>
21
+      var exports = {};
22
+    </script>
23
+    <script src="./dist/genfuns.js"></script>
24
+    <script src="./dist/genfun_formatter.js"></script>
25
+    <script src="./dist/main.js"></script>
26
+  </body>
21 27
 </html>
... ...
@@ -1,24 +1,22 @@
1 1
 {
2
-    "compilerOptions": {
3
-        "target": "es2017",
4
-        "baseUrl": "src",
5
-        "allowSyntheticDefaultImports": true,
6
-        "noEmit": true,
7
-        "checkJs": true,
8
-        "lib": [ "es2017" ],
9
-        "rootDirs": [
10
-            "src"
11
-        ],
12
-        "module": "commonjs"
13
-    },
14
-    "exclude": [
15
-        ".history/*",
16
-        "frontend",
17
-        "node_modules",
18
-        "node_modules/**/*",
19
-        "**/node_modules/**/*",
20
-        "**/node_modules/*",
21
-        "/.#*",
22
-        "**/.#*"
23
-    ]
2
+  "compilerOptions": {
3
+    "target": "es2017",
4
+    "baseUrl": "src",
5
+    "allowSyntheticDefaultImports": true,
6
+    "noEmit": true,
7
+    "checkJs": true,
8
+    "lib": ["es2017"],
9
+    "rootDirs": ["src"],
10
+    "module": "commonjs"
11
+  },
12
+  "exclude": [
13
+    ".history/*",
14
+    "frontend",
15
+    "node_modules",
16
+    "node_modules/**/*",
17
+    "**/node_modules/**/*",
18
+    "**/node_modules/*",
19
+    "/.#*",
20
+    "**/.#*"
21
+  ]
24 22
 }
... ...
@@ -1,46 +1,46 @@
1 1
 {
2
-    "author": "Ed L",
3
-    "license": "ISC",
4
-    "name": "js-generic-functions",
5
-    "version": "1.0.9",
6
-    "description": "A CLOS-inspired implementation of generic functions",
7
-    "repository": "https://github.com/fiddlerwoaroof/js-generic-functions",
8
-    "homepage": "https://fiddlerwoaroof.github.io/js-generic-functions/",
9
-    "main": "dist/genfuns.js",
10
-    "dependencies": {},
11
-    "devDependencies": {
12
-        "@babel/cli": "^7.10.4",
13
-        "@babel/core": "^7.10.4",
14
-        "@babel/plugin-proposal-object-rest-spread": "^7.10.4",
15
-        "@babel/preset-env": "^7.10.4",
16
-        "babel-core": "^7.0.0-bridge.0",
17
-        "eslint": "^7.1.0",
18
-        "eslint-plugin-react": "^7.20.3",
19
-        "jest": "^26.0.1",
20
-        "jest-junit": "^11.0.1",
21
-        "prettier": "^2.0.5"
22
-    },
23
-    "files": [
24
-        "/dist/*.js",
25
-        "/dist/*.css",
26
-        "/dist/*.html",
27
-        "/src/*.js",
28
-        "/src/*.css",
29
-        "/src/*.html"
30
-    ],
31
-    "scripts": {
32
-        "test": "jest src",
33
-        "format": "prettier --write .",
34
-        "build": "babel -d dist src",
35
-        "prepublishOnly": "babel -d dist src && jest src && eslint src"
36
-    },
37
-    "jest-junit": {
38
-        "outputDirectory": "./test-results/jest",
39
-        "outputName": "./results.xml"
40
-    },
41
-    "prettier": {
42
-        "trailingComma": "es5",
43
-        "jsxBracketSameLine": true,
44
-        "arrowParens": "avoid"
45
-    }
2
+  "author": "Ed L",
3
+  "license": "ISC",
4
+  "name": "js-generic-functions",
5
+  "version": "1.0.9",
6
+  "description": "A CLOS-inspired implementation of generic functions",
7
+  "repository": "https://github.com/fiddlerwoaroof/js-generic-functions",
8
+  "homepage": "https://fiddlerwoaroof.github.io/js-generic-functions/",
9
+  "main": "dist/genfuns.js",
10
+  "dependencies": {},
11
+  "devDependencies": {
12
+    "@babel/cli": "^7.10.4",
13
+    "@babel/core": "^7.10.4",
14
+    "@babel/plugin-proposal-object-rest-spread": "^7.10.4",
15
+    "@babel/preset-env": "^7.10.4",
16
+    "babel-core": "^7.0.0-bridge.0",
17
+    "eslint": "^7.1.0",
18
+    "eslint-plugin-react": "^7.20.3",
19
+    "jest": "^26.0.1",
20
+    "jest-junit": "^11.0.1",
21
+    "prettier": "^2.0.5"
22
+  },
23
+  "files": [
24
+    "/dist/*.js",
25
+    "/dist/*.css",
26
+    "/dist/*.html",
27
+    "/src/*.js",
28
+    "/src/*.css",
29
+    "/src/*.html"
30
+  ],
31
+  "scripts": {
32
+    "test": "jest src",
33
+    "format": "prettier --write .",
34
+    "build": "babel -d dist src",
35
+    "prepublishOnly": "babel -d dist src && jest src && eslint src"
36
+  },
37
+  "jest-junit": {
38
+    "outputDirectory": "./test-results/jest",
39
+    "outputName": "./results.xml"
40
+  },
41
+  "prettier": {
42
+    "trailingComma": "es5",
43
+    "jsxBracketSameLine": true,
44
+    "arrowParens": "avoid"
45
+  }
46 46
 }
... ...
@@ -1,4 +1,7 @@
1 1
 {
2
-    "presets": ["@babel/env", "@babel/preset-react"],
3
-    "plugins": ["@babel/plugin-transform-react-jsx", "@babel/plugin-proposal-object-rest-spread"]
2
+  "presets": ["@babel/env", "@babel/preset-react"],
3
+  "plugins": [
4
+    "@babel/plugin-transform-react-jsx",
5
+    "@babel/plugin-proposal-object-rest-spread"
6
+  ]
4 7
 }
... ...
@@ -2,18 +2,28 @@ export class Item {
2 2
   constructor(price) {
3 3
     this.price = price;
4 4
   }
5
-  get tax() { throw "not implemented"; }
6
-  get subtotal() { return this.price + this.tax; }
5
+  get tax() {
6
+    throw "not implemented";
7
+  }
8
+  get subtotal() {
9
+    return this.price + this.tax;
10
+  }
7 11
 }
8 12
 
9 13
 export class AlcoholicBeverage extends Item {
10
-  get tax() { return this.price * 0.25; }
14
+  get tax() {
15
+    return this.price * 0.25;
16
+  }
11 17
 }
12 18
 
13 19
 export class NormalFood extends Item {
14
-  get tax() { return 0; }
20
+  get tax() {
21
+    return 0;
22
+  }
15 23
 }
16 24
 
17 25
 export class NonFood extends Item {
18
-  get tax() { return this.price * 0.0825; }
26
+  get tax() {
27
+    return this.price * 0.0825;
28
+  }
19 29
 }
... ...
@@ -1,25 +1,51 @@
1 1
 <!DOCTYPE html>
2 2
 <html lang="en">
3
+  <head>
4
+    <meta charset="UTF-8" />
5
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
7
+    <title>Document</title>
8
+    <script src="dist/main.o.js" defer></script>
9
+    <style>
10
+      * {
11
+        box-sizing: border-box;
12
+      }
13
+      h1 > span {
14
+        display: inline-block;
15
+        white-space: nowrap;
16
+      }
17
+      h1 > span + span::before {
18
+        content: " ";
19
+        display: inline-block;
20
+      }
21
+      h1 .desc,
22
+      h1 .price {
23
+        display: inline;
24
+        width: auto;
25
+      }
26
+      ul {
27
+        padding: 0;
28
+        list-style: none;
29
+        width: 14em;
30
+        font-family: "Source Code Pro", monospace;
31
+      }
32
+      li {
33
+        text-align: right;
34
+      }
35
+      .desc {
36
+        display: inline-block;
37
+        vertical-align: baseline;
38
+        width: 75%;
39
+      }
40
+      .price {
41
+        display: inline-block;
42
+        vertical-align: baseline;
43
+        width: 25%;
44
+      }
45
+    </style>
46
+  </head>
3 47
 
4
-<head>
5
-  <meta charset="UTF-8">
6
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
-  <meta http-equiv="X-UA-Compatible" content="ie=edge">
8
-  <title>Document</title>
9
-  <script src="dist/main.o.js" defer></script>
10
-  <style>
11
-    * { box-sizing: border-box; }
12
-    h1 > span {display: inline-block; white-space: nowrap;}
13
-    h1 > span + span::before {content: ' '; display: inline-block; }
14
-    h1 .desc, h1 .price {display: inline; width: auto; }
15
-    ul { padding: 0; list-style: none; width: 14em; font-family: 'Source Code Pro', monospace }
16
-    li { text-align: right;}
17
-    .desc { display: inline-block; vertical-align: baseline; width: 75%;}
18
-    .price { display: inline-block; vertical-align: baseline; width: 25%; }
19
-  </style>
20
-</head>
21
-
22
-<body>
23
-  <main></main>
24
-</body>
25
-</html>
26 48
\ No newline at end of file
49
+  <body>
50
+    <main></main>
51
+  </body>
52
+</html>
... ...
@@ -1,31 +1,49 @@
1
-import React from 'react';
2
-import ReactDOM from 'react-dom';
3
-import '../src/genfun_formatter';
4
-import { Receipt } from './render';
5
-import * as m from './Model';
1
+import React from "react";
2
+import ReactDOM from "react-dom";
3
+import "../src/genfun_formatter";
4
+import { Receipt } from "./render";
5
+import * as m from "./Model";
6 6
 
7
-import * as gf from '../src/genfuns';
7
+import * as gf from "../src/genfuns";
8 8
 
9
-const Editable =
10
-  gf.defgeneric("Editable", "props")
11
-    .around([Object], function (_) {
12
-      return <div style={{ display: 'inline-block' }}>{this.call_next_method()} </div>
13
-    })
14
-    .primary([gf.Shape("label", "htmlFor")], ({ label, htmlFor }) =>
15
-      <label {...{htmlFor}}>{label}</label>)
16
-    .primary([gf.Shape("label", "htmlFor", "value")], function ({ value, onChange }) {
17
-      return <>
9
+const Editable = gf
10
+  .defgeneric("Editable", "props")
11
+  .around([Object], function (_) {
12
+    return (
13
+      <div style={{ display: "inline-block" }}>{this.call_next_method()} </div>
14
+    );
15
+  })
16
+  .primary([gf.Shape("label", "htmlFor")], ({ label, htmlFor }) => (
17
+    <label {...{ htmlFor }}>{label}</label>
18
+  ))
19
+  .primary([gf.Shape("label", "htmlFor", "value")], function ({
20
+    value,
21
+    onChange,
22
+  }) {
23
+    return (
24
+      <>
18 25
         {this.call_next_method()}
19 26
         {onChange ? null : <span> {value}</span>}
20 27
       </>
21
-    })
22
-    .primary([gf.Shape("label", "htmlFor", "value", "onChange")], function ({ value, htmlFor, onChange }) {
23
-      return <>
28
+    );
29
+  })
30
+  .primary([gf.Shape("label", "htmlFor", "value", "onChange")], function ({
31
+    value,
32
+    htmlFor,
33
+    onChange,
34
+  }) {
35
+    return (
36
+      <>
24 37
         {this.call_next_method()}
25
-        <input type="text" value={value} id={htmlFor} name={htmlFor} onChange={onChange}></input>
38
+        <input
39
+          type="text"
40
+          value={value}
41
+          id={htmlFor}
42
+          name={htmlFor}
43
+          onChange={onChange}></input>
26 44
       </>
27
-    })
28
-    .fn;
45
+    );
46
+  }).fn;
29 47
 
30 48
 class Field extends React.Component {
31 49
   constructor(props) {
... ...
@@ -33,21 +51,26 @@ class Field extends React.Component {
33 51
     this.state = { editing: false, val: props.value };
34 52
   }
35 53
   click() {
36
-    this.setState(() => ({ editing: !this.state.editing, val: this.state.val }));
54
+    this.setState(() => ({
55
+      editing: !this.state.editing,
56
+      val: this.state.val,
57
+    }));
37 58
   }
38 59
   onChange(e) {
39 60
     const val = e.target.value;
40
-    this.setState(() => ({ editing: true, val }))
61
+    this.setState(() => ({ editing: true, val }));
41 62
   }
42 63
   render() {
43 64
     const editingProps = {};
44 65
     if (this.state.editing) {
45 66
       editingProps.onChange = this.onChange.bind(this);
46 67
     }
47
-    return <div>
48
-      <Editable {...this.props} {...editingProps} value={this.state.val} />
49
-      <button onClick={this.click.bind(this)}>Toggle</button>
50
-    </div>
68
+    return (
69
+      <div>
70
+        <Editable {...this.props} {...editingProps} value={this.state.val} />
71
+        <button onClick={this.click.bind(this)}>Toggle</button>
72
+      </div>
73
+    );
51 74
   }
52 75
 }
53 76
 
... ...
@@ -56,17 +79,19 @@ ReactDOM.render(
56 79
     <Field label="the field" htmlFor="the-field" value="foo" />
57 80
     <Editable label="bazquuxes" htmlFor="bazquux" value="foo" display />
58 81
     <Editable label="bazquuxes" htmlFor="bazquux" value="foo" editable />
59
-    <Receipt items={[
60
-      new m.AlcoholicBeverage(11),
61
-      new m.AlcoholicBeverage(12),
62
-      new m.AlcoholicBeverage(13),
63
-      new m.NormalFood(11),
64
-      new m.NonFood(11),
65
-      new m.AlcoholicBeverage(10)
66
-    ]} />
82
+    <Receipt
83
+      items={[
84
+        new m.AlcoholicBeverage(11),
85
+        new m.AlcoholicBeverage(12),
86
+        new m.AlcoholicBeverage(13),
87
+        new m.NormalFood(11),
88
+        new m.NonFood(11),
89
+        new m.AlcoholicBeverage(10),
90
+      ]}
91
+    />
67 92
   </div>,
68
-  document.querySelector('main'),
93
+  document.querySelector("main"),
69 94
   () => {
70
-    console.log('rendered');
95
+    console.log("rendered");
71 96
   }
72
-);
73 97
\ No newline at end of file
98
+);
... ...
@@ -1,8 +1,8 @@
1
-import * as m from './Model';
2
-import * as r from './render';
1
+import * as m from "./Model";
2
+import * as r from "./render";
3 3
 
4
-describe('Model', () => {
5
-  test('base behavior', () => {
4
+describe("Model", () => {
5
+  test("base behavior", () => {
6 6
     const Foo = class extends m.Item {
7 7
       get tax() {
8 8
         return 1;
... ...
@@ -13,10 +13,9 @@ describe('Model', () => {
13 13
     expect(new Foo(2).subtotal).toEqual(3);
14 14
   });
15 15
 
16
-  test('taxes', () => {
16
+  test("taxes", () => {
17 17
     expect(Math.floor(new m.NonFood(1).tax * 10000)).toEqual(825);
18 18
     expect(Math.floor(new m.AlcoholicBeverage(1).tax * 100)).toEqual(25);
19 19
     expect(Math.floor(new m.NormalFood(1).tax)).toEqual(0);
20
-  })
20
+  });
21 21
 });
22
-
... ...
@@ -1,30 +1,30 @@
1 1
 {
2
-    "author": "Ed L",
3
-    "license": "ISC",
4
-    "name": "react-demo",
5
-    "version": "1.0.7",
6
-    "description": "A CLOS-inspired implementation of generic functions",
7
-    "dependencies": {
8
-        "react": "^16.5.0",
9
-        "react-dom": "^16.5.0"
10
-    },
11
-    "devDependencies": {
12
-        "@babel/cli": "^7.5.0",
13
-        "@babel/core": "^7.5.0",
14
-        "@babel/plugin-proposal-object-rest-spread": "^7.5.0",
15
-        "@babel/plugin-transform-react-jsx": "^7.0.0",
16
-        "@babel/preset-env": "^7.5.0",
17
-        "@babel/preset-react": "^7.0.0",
18
-        "babel-core": "^7.0.0-bridge.0",
19
-        "eslint-plugin-react": "^7.11.1",
20
-        "npm": "^6.13.4",
21
-        "ramda": "*",
22
-        "rollup": "^1.16.6",
23
-        "rollup-plugin-babel": "^4.3.2",
24
-        "rollup-plugin-commonjs": "^10.0.0",
25
-        "rollup-plugin-livereload": "^1.0.0",
26
-        "rollup-plugin-node-resolve": "^5.0.0",
27
-        "rollup-plugin-replace": "^2.0.0",
28
-        "rollup-plugin-serve": "^1.0.1"
29
-    }
2
+  "author": "Ed L",
3
+  "license": "ISC",
4
+  "name": "react-demo",
5
+  "version": "1.0.7",
6
+  "description": "A CLOS-inspired implementation of generic functions",
7
+  "dependencies": {
8
+    "react": "^16.5.0",
9
+    "react-dom": "^16.5.0"
10
+  },
11
+  "devDependencies": {
12
+    "@babel/cli": "^7.5.0",
13
+    "@babel/core": "^7.5.0",
14
+    "@babel/plugin-proposal-object-rest-spread": "^7.5.0",
15
+    "@babel/plugin-transform-react-jsx": "^7.0.0",
16
+    "@babel/preset-env": "^7.5.0",
17
+    "@babel/preset-react": "^7.0.0",
18
+    "babel-core": "^7.0.0-bridge.0",
19
+    "eslint-plugin-react": "^7.11.1",
20
+    "npm": "^6.13.4",
21
+    "ramda": "*",
22
+    "rollup": "^1.16.6",
23
+    "rollup-plugin-babel": "^4.3.2",
24
+    "rollup-plugin-commonjs": "^10.0.0",
25
+    "rollup-plugin-livereload": "^1.0.0",
26
+    "rollup-plugin-node-resolve": "^5.0.0",
27
+    "rollup-plugin-replace": "^2.0.0",
28
+    "rollup-plugin-serve": "^1.0.1"
29
+  }
30 30
 }
... ...
@@ -1,59 +1,78 @@
1
-import React from 'react';
2
-import * as gf from '../src/genfuns';
3
-import * as m from './Model';
1
+import React from "react";
2
+import * as gf from "../src/genfuns";
3
+import * as m from "./Model";
4 4
 
5 5
 class Summary {
6
-  constructor(wrapper = 'span') {
6
+  constructor(wrapper = "span") {
7 7
     this.wrapper = wrapper;
8 8
   }
9 9
 }
10
-class Detail { }
10
+class Detail {}
11 11
 
12
-const total_receipt = items => items.reduce((acc, item) => acc + item.subtotal, 0);
12
+const total_receipt = items =>
13
+  items.reduce((acc, item) => acc + item.subtotal, 0);
13 14
 const subtotal = items => items.reduce((acc, item) => acc + item.price, 0);
14 15
 const total_tax = items => items.reduce((acc, item) => acc + item.tax, 0);
15 16
 
16 17
 const display_money = amount => amount.toFixed(2);
17 18
 
18 19
 const ItemLabel = ({ desc, amount, wrapper, ...restProps }) =>
19
-  React.createElement(wrapper, restProps,
20
-    [
21
-      <span className="desc" key="0"> {desc}: </span>,
22
-      <span className="price" key="1">{display_money(amount)}</span>
23
-    ]
24
-  );
20
+  React.createElement(wrapper, restProps, [
21
+    <span className="desc" key="0">
22
+      {" "}
23
+      {desc}:{" "}
24
+    </span>,
25
+    <span className="price" key="1">
26
+      {display_money(amount)}
27
+    </span>,
28
+  ]);
25 29
 
26
-export const Items = gf.defgeneric("Items", "animaltorender")
30
+export const Items = gf
31
+  .defgeneric("Items", "animaltorender")
27 32
   .primary([gf.Shape("items", "view")], ({ items, view }) => Items(items, view))
28 33
   .primary([Array, Summary], (items, view) => (
29 34
     <>
30
-      <ItemLabel desc="Subtotal" amount={subtotal(items)} wrapper={view.wrapper} />
35
+      <ItemLabel
36
+        desc="Subtotal"
37
+        amount={subtotal(items)}
38
+        wrapper={view.wrapper}
39
+      />
31 40
       <ItemLabel desc="Tax" amount={total_tax(items)} wrapper={view.wrapper} />
32
-      <ItemLabel desc="Total" amount={total_receipt(items)} wrapper={view.wrapper} />
41
+      <ItemLabel
42
+        desc="Total"
43
+        amount={total_receipt(items)}
44
+        wrapper={view.wrapper}
45
+      />
33 46
     </>
34 47
   ))
35 48
   .primary([Array, Detail], items => (
36 49
     <ul>
37
-      {items.map((a, idx) => <Item item={a} key={idx} />, items)}
38
-      <Items items={items} view={new Summary('li')} />
50
+      {items.map(
51
+        (a, idx) => (
52
+          <Item item={a} key={idx} />
53
+        ),
54
+        items
55
+      )}
56
+      <Items items={items} view={new Summary("li")} />
39 57
     </ul>
40
-  ))
41
-  .fn;
58
+  )).fn;
42 59
 
43
-export const Item = gf.defgeneric("Item", "itemtorender")
60
+export const Item = gf
61
+  .defgeneric("Item", "itemtorender")
44 62
   .primary([gf.Shape("item")], ({ item }) => Item(item))
45 63
   .around([m.Item], function (_) {
46 64
     const [desc, price] = this.call_next_method();
47
-    return <ItemLabel desc={desc} amount={price} wrapper='li' />;
65
+    return <ItemLabel desc={desc} amount={price} wrapper="li" />;
48 66
   })
49 67
   .primary([m.NonFood], item => ["Non-food Item", item.price])
50 68
   .primary([m.NormalFood], item => ["Food", item.price])
51
-  .primary([m.AlcoholicBeverage], item => ["Alcohol", item.price])
52
-  .fn;
69
+  .primary([m.AlcoholicBeverage], item => ["Alcohol", item.price]).fn;
53 70
 
54
-export const Receipt = ({items}) => (
71
+export const Receipt = ({ items }) => (
55 72
   <div>
56
-    <h1><Items {...{ items }} view={new Summary()} /></h1>
73
+    <h1>
74
+      <Items {...{ items }} view={new Summary()} />
75
+    </h1>
57 76
     <Items {...{ items }} view={new Detail()} />
58 77
   </div>
59 78
 );
... ...
@@ -1,22 +1,22 @@
1
-import babel from 'rollup-plugin-babel';
2
-import npm_resolve from 'rollup-plugin-node-resolve';
3
-import commonjs from 'rollup-plugin-commonjs';
4
-import replace from 'rollup-plugin-replace';
5
-import livereload from 'rollup-plugin-livereload';
1
+import babel from "rollup-plugin-babel";
2
+import npm_resolve from "rollup-plugin-node-resolve";
3
+import commonjs from "rollup-plugin-commonjs";
4
+import replace from "rollup-plugin-replace";
5
+import livereload from "rollup-plugin-livereload";
6 6
 
7 7
 export default {
8
-  input: 'main.js',
8
+  input: "main.js",
9 9
   output: {
10
-    file: 'dist/main.o.js',
10
+    file: "dist/main.o.js",
11 11
     browser: true,
12 12
     sourcemap: true,
13
-  format: 'iife',
13
+    format: "iife",
14 14
   },
15 15
   plugins: [
16 16
     //livereload({watch: 'dist'}),
17
-    replace({'process.env.NODE_ENV': JSON.stringify('development')}),
18
-    babel({ exclude: 'node_modules/**'  }),
17
+    replace({ "process.env.NODE_ENV": JSON.stringify("development") }),
18
+    babel({ exclude: "node_modules/**" }),
19 19
     npm_resolve({ module: true, jsnext: true, main: true, browser: true }),
20 20
     commonjs(),
21
-  ]
21
+  ],
22 22
 };
... ...
@@ -1,63 +1,73 @@
1 1
 /* eslint-disable */
2 2
 
3 3
 window.devtoolsFormatters = [
4
-    {
5
-        header(obj, config) {
6
-            if (config && config.genfunFormatter) {
7
-                return ["div", {}, config.key];
8
-            } else if (!(obj.gf || obj instanceof GenericFunction)) {
9
-                return null;
10
-            } else if (obj.gf) {
11
-                const args = obj.gf.lambda_list.join(', ');
12
-                const method_count = obj.gf.methods.length
13
-                return [
14
-                    'div', {},
15
-                    `GenericFunction lambda: ${obj.gf.name}(${args}) `
16
-                    + `[${method_count} methods]`
17
-                ];
4
+  {
5
+    header(obj, config) {
6
+      if (config && config.genfunFormatter) {
7
+        return ["div", {}, config.key];
8
+      } else if (!(obj.gf || obj instanceof GenericFunction)) {
9
+        return null;
10
+      } else if (obj.gf) {
11
+        const args = obj.gf.lambda_list.join(", ");
12
+        const method_count = obj.gf.methods.length;
13
+        return [
14
+          "div",
15
+          {},
16
+          `GenericFunction lambda: ${obj.gf.name}(${args}) ` +
17
+            `[${method_count} methods]`,
18
+        ];
19
+      } else {
20
+        const args = obj.lambda_list.join(", ");
21
+        const method_count = obj.methods.length;
22
+        return [
23
+          "div",
24
+          {},
25
+          `#<GenericFunction: ${obj.name}(${args}) [${method_count} methods]>`,
26
+        ];
27
+      }
28
+    },
29
+    hasBody(obj) {
30
+      return obj instanceof GenericFunction || obj instanceof StandardMethod;
31
+    },
32
+    body(obj, config) {
33
+      if (!(obj instanceof GenericFunction || obj instanceof StandardMethod)) {
34
+        return null;
35
+      } else if (obj instanceof StandardMethod) {
36
+        return ["div", { style: "margin-left: 2em" }].concat(
37
+          Object.keys(obj).map(key => {
38
+            if (obj[key] instanceof String) {
39
+              return ["div", {}, `${key}: ${obj[key]},`];
18 40
             } else {
19
-                const args = obj.lambda_list.join(', ');
20
-                const method_count = obj.methods.length
21
-                return [
22
-                    'div', {},
23
-                    `#<GenericFunction: ${obj.name}(${args}) [${method_count} methods]>`
24
-                ];
25
-            }
26
-        },
27
-        hasBody(obj) {return obj instanceof GenericFunction || obj instanceof StandardMethod;},
28
-        body(obj, config) {
29
-            if (! (obj instanceof GenericFunction || obj instanceof StandardMethod) ) {
30
-                return null;
31
-            } else if ( obj instanceof StandardMethod ) {
32
-                return ["div", {style: 'margin-left: 2em'}].concat(
33
-                    Object.keys(obj).map(
34
-                        key => {
35
-                            if (obj[key] instanceof String) {
36
-                                return ["div", {}, `${key}: ${obj[key]},`];
37
-                            } else {
38
-                                return ["div", {}, `${key}: `, ["object", {object: obj[key]}], ','];
39
-                            }
40
-                        }
41
-                    )
42
-                );
41
+              return [
42
+                "div",
43
+                {},
44
+                `${key}: `,
45
+                ["object", { object: obj[key] }],
46
+                ",",
47
+              ];
43 48
             }
49
+          })
50
+        );
51
+      }
44 52
 
45
-            const children = obj.methods.map(
46
-                (method,idx) => {
47
-                    const child = [
48
-                        "object", {
49
-                            object: method,
50
-                            config: {
51
-                                genfunFormatter: true,
52
-                                key: `#<StandardMethod ${method.qualifiers.map(x => ':'+x.toString().slice(7,-1)).join(' ')} (${method.specializers.map(x => x.name.toString())})>`,
53
-                            },
54
-                        },
55
-                    ];
56
-                    return ["div", {style: `margin-left: 2em;`},
57
-                            child]
58
-                }
59
-            );
60
-            return ["div", {}].concat(children);
61
-        }
62
-    }
53
+      const children = obj.methods.map((method, idx) => {
54
+        const child = [
55
+          "object",
56
+          {
57
+            object: method,
58
+            config: {
59
+              genfunFormatter: true,
60
+              key: `#<StandardMethod ${method.qualifiers
61
+                .map(x => ":" + x.toString().slice(7, -1))
62
+                .join(" ")} (${method.specializers.map(x =>
63
+                x.name.toString()
64
+              )})>`,
65
+            },
66
+          },
67
+        ];
68
+        return ["div", { style: `margin-left: 2em;` }, child];
69
+      });
70
+      return ["div", {}].concat(children);
71
+    },
72
+  },
63 73
 ];
... ...
@@ -16,7 +16,7 @@ const Method = {
16 16
   qualifiers: [],
17 17
   specializers: [],
18 18
   body: () => {},
19
-  generic_function: null
19
+  generic_function: null,
20 20
 };
21 21
 
22 22
 let genfun_prototype = {
... ...
@@ -41,15 +41,15 @@ let genfun_prototype = {
41 41
   },
42 42
   get fn() {
43 43
     const gf = this;
44
-    const lambda = function() {
44
+    const lambda = function () {
45 45
       return apply_generic_function(gf, [].slice.call(arguments));
46 46
     }.bind(gf);
47 47
     return Object.defineProperties(lambda, {
48 48
       name: { value: gf.name },
49 49
       lambda_list: { value: gf.lambda_list },
50
-      gf: { value: gf }
50
+      gf: { value: gf },
51 51
     });
52
-  }
52
+  },
53 53
 };
54 54
 
55 55
 /**
... ...
@@ -146,7 +146,7 @@ function method_more_specific_p(m1, m2 /*, required_classes*/) {
146 146
   let result = null;
147 147
   for (let [spec1, spec2] of m1specializers.map((el, idx) => [
148 148
     el,
149
-    m2specializers[idx]
149
+    m2specializers[idx],
150 150
   ])) {
151 151
     if (spec1 !== spec2) {
152 152
       result = sub_specializer_p(spec1, spec2);
... ...
@@ -168,7 +168,7 @@ export function sub_specializer_p(c1, c2) {
168 168
 }
169 169
 
170 170
 const idS = Symbol.for("id");
171
-Object.prototype[idS] = function() {
171
+Object.prototype[idS] = function () {
172 172
   return this;
173 173
 };
174 174
 
... ...
@@ -179,7 +179,7 @@ Specializer.prototype = {
179 179
   },
180 180
   super_of(_obj) {
181 181
     return false;
182
-  }
182
+  },
183 183
 };
184 184
 
185 185
 function isSuperset(superset, subset) {
... ...
@@ -218,7 +218,7 @@ Shape.prototype = Object.assign(new Specializer(), {
218 218
     } else {
219 219
       return isSuperset(spec.keys, this.keys);
220 220
     }
221
-  }
221
+  },
222 222
 });
223 223
 
224 224
 // function trace(fun) {
... ...
@@ -354,7 +354,7 @@ function apply_methods(gf, args, applicable_methods) {
354 354
   afters.reverse();
355 355
 
356 356
   const main_call = Object.defineProperty(
357
-    function() {
357
+    function () {
358 358
       if (primaries.length === 0) {
359 359
         throw new NoPrimaryMethodError(`No primary method for ${gf.name}`);
360 360
       }
... ...
@@ -409,7 +409,7 @@ function apply_method(method, args, next_methods) {
409 409
 
410 410
     get next_method_p() {
411 411
       return next_methods.length !== 0;
412
-    }
412
+    },
413 413
   };
414 414
 
415 415
   return method.body
... ...
@@ -1,303 +1,361 @@
1
-import * as uut from './genfuns';
2
-import { fail } from 'assert';
3
-
4
-describe('matches_specializer', () => {
5
-    test('works in expected cases', () => {
6
-        function AThing() { }
7
-        const an_instance = new AThing();
8
-
9
-        expect(uut.matches_specializer(an_instance, AThing)).toBeTruthy();
10
-        expect(uut.matches_specializer(an_instance, String)).toBeFalsy();
11
-        expect(uut.matches_specializer(an_instance, Object)).toBeTruthy();
12
-
13
-        expect(uut.matches_specializer([], Array)).toBeTruthy();
14
-        expect(uut.matches_specializer([], Object)).toBeTruthy();
15
-        expect(uut.matches_specializer([], Number)).toBeFalsy();
16
-
17
-        function Foo() { }
18
-        Foo.prototype = Object.create(null);
19
-        const inst = new Foo();
20
-        expect(uut.matches_specializer(inst, Foo)).toBeTruthy();
21
-        expect(uut.matches_specializer(inst, Object)).toBeFalsy();
22
-
23
-        expect(uut.matches_specializer({ a: 1 }, uut.Shape('a'))).toBeTruthy();
24
-        expect(uut.matches_specializer({ a: 1, b: 2 }, uut.Shape('a'))).toBeTruthy();
25
-        expect(uut.matches_specializer({ b: 2 }, uut.Shape('a'))).toBeFalsy();
26
-
27
-        expect(uut.matches_specializer({ a: 1, b: 2, c: 3 }, uut.Shape('a', 'b', 'c'))).toBeTruthy();
28
-        expect(uut.matches_specializer({ a: 1, b: 2, c: 3, d: 4 }, uut.Shape('a', 'b', 'c'))).toBeTruthy();
29
-        expect(uut.matches_specializer({ a: 1, c: 3 }, uut.Shape('a', 'b', 'c'))).toBeFalsy();
30
-        expect(uut.matches_specializer({ c: 3 }, uut.Shape('a', 'b', 'c'))).toBeFalsy();
31
-        expect(uut.matches_specializer({ d: 3 }, uut.Shape('a', 'b', 'c'))).toBeFalsy();
32
-    });
33
-
34
-    test('null behavior', () => {
35
-        expect(uut.matches_specializer(null, null)).toBeTruthy();
36
-        expect(uut.matches_specializer(null, Number)).toBeFalsy();
37
-        expect(uut.matches_specializer(null, String)).toBeFalsy();
38
-        expect(uut.matches_specializer(null, Object)).toBeFalsy();
39
-    });
40
-
41
-    test('undefined (the value) behavior', () => {
42
-        expect(uut.matches_specializer(undefined, undefined)).toBeTruthy();
43
-        expect(uut.matches_specializer(undefined, Number)).toBeFalsy();
44
-        expect(uut.matches_specializer(undefined, String)).toBeFalsy();
45
-        expect(uut.matches_specializer(undefined, Object)).toBeFalsy();
46
-    });
47
-
48
-    test('works for numbers', () => {
49
-        expect(uut.matches_specializer(new Number(1), Number)).toBeTruthy();
50
-        expect(uut.matches_specializer(new Number(1), Object)).toBeTruthy();
51
-        expect(uut.matches_specializer(new Number(1), String)).toBeFalsy();
52
-
53
-        expect(uut.matches_specializer(1, Number)).toBeTruthy();
54
-        expect(uut.matches_specializer(1, Object)).toBeTruthy();
55
-        expect(uut.matches_specializer(1, String)).toBeFalsy();
56
-    });
57
-
58
-    test('handles strings', () => {
59
-        expect(uut.matches_specializer(new String("foobar"), String)).toBeTruthy();
60
-        expect(uut.matches_specializer(new String("foobar"), Object)).toBeTruthy();
61
-
62
-        expect(uut.matches_specializer("1", String)).toBeTruthy();
63
-        expect(uut.matches_specializer("1", Object)).toBeTruthy();
64
-        expect(uut.matches_specializer("1", Number)).toBeFalsy();
65
-    })
1
+import * as uut from "./genfuns";
2
+import { fail } from "assert";
3
+
4
+describe("matches_specializer", () => {
5
+  test("works in expected cases", () => {
6
+    function AThing() {}
7
+    const an_instance = new AThing();
8
+
9
+    expect(uut.matches_specializer(an_instance, AThing)).toBeTruthy();
10
+    expect(uut.matches_specializer(an_instance, String)).toBeFalsy();
11
+    expect(uut.matches_specializer(an_instance, Object)).toBeTruthy();
12
+
13
+    expect(uut.matches_specializer([], Array)).toBeTruthy();
14
+    expect(uut.matches_specializer([], Object)).toBeTruthy();
15
+    expect(uut.matches_specializer([], Number)).toBeFalsy();
16
+
17
+    function Foo() {}
18
+    Foo.prototype = Object.create(null);
19
+    const inst = new Foo();
20
+    expect(uut.matches_specializer(inst, Foo)).toBeTruthy();
21
+    expect(uut.matches_specializer(inst, Object)).toBeFalsy();
22
+
23
+    expect(uut.matches_specializer({ a: 1 }, uut.Shape("a"))).toBeTruthy();
24
+    expect(
25
+      uut.matches_specializer({ a: 1, b: 2 }, uut.Shape("a"))
26
+    ).toBeTruthy();
27
+    expect(uut.matches_specializer({ b: 2 }, uut.Shape("a"))).toBeFalsy();
28
+
29
+    expect(
30
+      uut.matches_specializer({ a: 1, b: 2, c: 3 }, uut.Shape("a", "b", "c"))
31
+    ).toBeTruthy();
32
+    expect(
33
+      uut.matches_specializer(
34
+        { a: 1, b: 2, c: 3, d: 4 },
35
+        uut.Shape("a", "b", "c")
36
+      )
37
+    ).toBeTruthy();
38
+    expect(
39
+      uut.matches_specializer({ a: 1, c: 3 }, uut.Shape("a", "b", "c"))
40
+    ).toBeFalsy();
41
+    expect(
42
+      uut.matches_specializer({ c: 3 }, uut.Shape("a", "b", "c"))
43
+    ).toBeFalsy();
44
+    expect(
45
+      uut.matches_specializer({ d: 3 }, uut.Shape("a", "b", "c"))
46
+    ).toBeFalsy();
47
+  });
48
+
49
+  test("null behavior", () => {
50
+    expect(uut.matches_specializer(null, null)).toBeTruthy();
51
+    expect(uut.matches_specializer(null, Number)).toBeFalsy();
52
+    expect(uut.matches_specializer(null, String)).toBeFalsy();
53
+    expect(uut.matches_specializer(null, Object)).toBeFalsy();
54
+  });
55
+
56
+  test("undefined (the value) behavior", () => {
57
+    expect(uut.matches_specializer(undefined, undefined)).toBeTruthy();
58
+    expect(uut.matches_specializer(undefined, Number)).toBeFalsy();
59
+    expect(uut.matches_specializer(undefined, String)).toBeFalsy();
60
+    expect(uut.matches_specializer(undefined, Object)).toBeFalsy();
61
+  });
62
+
63
+  test("works for numbers", () => {
64
+    expect(uut.matches_specializer(new Number(1), Number)).toBeTruthy();
65
+    expect(uut.matches_specializer(new Number(1), Object)).toBeTruthy();
66
+    expect(uut.matches_specializer(new Number(1), String)).toBeFalsy();
67
+
68
+    expect(uut.matches_specializer(1, Number)).toBeTruthy();
69
+    expect(uut.matches_specializer(1, Object)).toBeTruthy();
70
+    expect(uut.matches_specializer(1, String)).toBeFalsy();
71
+  });
72
+
73
+  test("handles strings", () => {
74
+    expect(uut.matches_specializer(new String("foobar"), String)).toBeTruthy();
75
+    expect(uut.matches_specializer(new String("foobar"), Object)).toBeTruthy();
76
+
77
+    expect(uut.matches_specializer("1", String)).toBeTruthy();
78
+    expect(uut.matches_specializer("1", Object)).toBeTruthy();
79
+    expect(uut.matches_specializer("1", Number)).toBeFalsy();
80
+  });
66 81
 });
67 82
 
68
-describe('defgeneric', () => {
69
-    test('methods get called appropriately', () => {
70
-        expect(
71
-            uut.defgeneric("testing1", "a", "b")
72
-                .primary([Object, Object], (_, __) => 1)
73
-                .fn(1, 2)
74
-        ).toEqual(1);
75
-
76
-        try {
77
-            uut.defgeneric("foobar", "a")
78
-                .primary([String], function (a) { })
79
-                .fn({});
80
-            fail();
81
-        } catch (err) {
82
-            expect(err).toBeInstanceOf(uut.NoApplicableMethodError);
83
-        }
84
-
85
-        expect(
86
-            uut.defgeneric("testing1", "a", "b")
87
-                .primary([Number, Number], (_, __) => 1)
88
-                .fn(1, 2)
89
-        ).toEqual(1);
90
-
91
-        expect(
92
-            uut.defgeneric("testing1", "a", "b")
93
-                .primary([Number, Number], (_, __) => 2)
94
-                .primary([String, String], (_, __) => 1)
95
-                .fn("1", "2")
96
-        ).toEqual(1);
97
-
98
-        let firstCounts = 0;
99
-        expect(
100
-            uut.defgeneric("testing1", "a", "b")
101
-                .primary([Number, Number], (_, __) => firstCounts += 1)
102
-                .primary([String, String], (_, __) => firstCounts += 1)
103
-                .fn("1", "2")
104
-        ).toEqual(1);
105
-        expect(firstCounts).toEqual(1);
106
-
107
-        let secondCounts = 0;
108
-        expect(
109
-            uut.defgeneric("testing1", "a", "b")
110
-                .primary([Object, Object], (_, __) => secondCounts += 1)
111
-                .primary([String, String], (_, __) => secondCounts += 1)
112
-                .fn("1", "2")
113
-        ).toEqual(1);
114
-        expect(secondCounts).toEqual(1);
115
-
116
-        let thirdCounts = 0;
117
-        expect(
118
-            uut.defgeneric("testing1", "a", "b")
119
-                .before([Object, Object], (_, __) => thirdCounts += 1)
120
-                .primary([String, String], (_, __) => 'hi')
121
-                .after([Object, String], (_, __) => thirdCounts += 1)
122
-                .fn("1", "2")
123
-        ).toEqual('hi');
124
-        expect(thirdCounts).toEqual(2);
125
-
126
-        expect(
127
-            uut.defgeneric("foobar", "a")
128
-                .primary([Object], function (a) {
129
-                    return 1
130
-                })
131
-                .primary([String], function (a) {
132
-                    return 2
133
-                })
134
-                .fn("foobar"))
135
-            .toEqual(2);
136
-    });
137
-
138
-    test('next-method-p works', () => {
139
-        expect.assertions(3);
140
-
141
-        uut.defgeneric("foobar", "a")
142
-            .primary([Object], function (a) {
143
-                expect(this.next_method_p).toBe(false);
144
-            })
145
-            .fn({});
146
-
147
-        uut.defgeneric("foobar", "a")
148
-            .primary([Object], function (a) {
149
-                expect(this.next_method_p).toBe(false);
150
-            })
151
-            .primary([String], function (a) {
152
-                expect(this.next_method_p).toBe(true);
153
-            })
154
-            .fn("foobar");
155
-
156
-        uut.defgeneric("foobar", "a")
157
-            .primary([Object], function (a) {
158
-                expect(this.next_method_p).toBe(false);
159
-            })
160
-            .primary([String], function (a) {
161
-                expect(this.next_method_p).toBe(true);
162
-            })
163
-            .fn(1);
164
-
165
-    });
166
-
167
-    test('call-next-method works', () => {
168
-        try {
169
-            uut.defgeneric("foobar", "a")
170
-                .primary([Object], function (a) {
171
-                    this.call_next_method();
172
-                })
173
-                .primary([String], function (a) {
174
-                    return 1;
175
-                })
176
-                .fn({})
177
-            fail();
178
-        } catch (err) {
179
-            expect(err).toBeInstanceOf(uut.NoNextMethodError);
180
-        }
181
-
182
-        expect(
183
-            uut.defgeneric("foobar", "a")
184
-                .primary([Object], function (a) {
185
-                    return 1;
186
-                })
187
-                .primary([String], function (a) {
188
-                    return this.call_next_method();
189
-                })
190
-                .fn("foobar")
191
-        ).toEqual(1);
192
-
193
-        expect(
194
-            uut.defgeneric("foobar", "a", "b")
195
-                .primary([String, String], function (a, b) {
196
-                    return `1${this.call_next_method()}`;
197
-                })
198
-                .primary([Object, String], function (a, b) {
199
-                    return `3${this.call_next_method()}`;
200
-                })
201
-                .primary([String, Object], function (a, b) {
202
-                    return `2${this.call_next_method()}`;
203
-                })
204
-                .primary([Object, Object], function (a, b) {
205
-                    return `4`;
206
-                }).fn("a", "b")
207
-        ).toEqual("1234");
208
-
209
-        try {
210
-            uut.defgeneric("foobar", "a")
211
-                .primary([Object], function (a) {
212
-                    this.call_next_method();
213
-                })
214
-                .fn({});
215
-            fail();
216
-        } catch (err) {
217
-            expect(err).toBeInstanceOf(uut.NoNextMethodError);
218
-        }
219
-
220
-    });
83
+describe("defgeneric", () => {
84
+  test("methods get called appropriately", () => {
85
+    expect(
86
+      uut
87
+        .defgeneric("testing1", "a", "b")
88
+        .primary([Object, Object], (_, __) => 1)
89
+        .fn(1, 2)
90
+    ).toEqual(1);
91
+
92
+    try {
93
+      uut
94
+        .defgeneric("foobar", "a")
95
+        .primary([String], function (a) {})
96
+        .fn({});
97
+      fail();
98
+    } catch (err) {
99
+      expect(err).toBeInstanceOf(uut.NoApplicableMethodError);
100
+    }
101
+
102
+    expect(
103
+      uut
104
+        .defgeneric("testing1", "a", "b")
105
+        .primary([Number, Number], (_, __) => 1)
106
+        .fn(1, 2)
107
+    ).toEqual(1);
108
+
109
+    expect(
110
+      uut
111
+        .defgeneric("testing1", "a", "b")
112
+        .primary([Number, Number], (_, __) => 2)
113
+        .primary([String, String], (_, __) => 1)
114
+        .fn("1", "2")
115
+    ).toEqual(1);
116
+
117
+    let firstCounts = 0;
118
+    expect(
119
+      uut
120
+        .defgeneric("testing1", "a", "b")
121
+        .primary([Number, Number], (_, __) => (firstCounts += 1))
122
+        .primary([String, String], (_, __) => (firstCounts += 1))
123
+        .fn("1", "2")
124
+    ).toEqual(1);
125
+    expect(firstCounts).toEqual(1);
126
+
127
+    let secondCounts = 0;
128
+    expect(
129
+      uut
130
+        .defgeneric("testing1", "a", "b")
131
+        .primary([Object, Object], (_, __) => (secondCounts += 1))
132
+        .primary([String, String], (_, __) => (secondCounts += 1))
133
+        .fn("1", "2")
134
+    ).toEqual(1);
135
+    expect(secondCounts).toEqual(1);
136
+
137
+    let thirdCounts = 0;
138
+    expect(
139
+      uut
140
+        .defgeneric("testing1", "a", "b")
141
+        .before([Object, Object], (_, __) => (thirdCounts += 1))
142
+        .primary([String, String], (_, __) => "hi")
143
+        .after([Object, String], (_, __) => (thirdCounts += 1))
144
+        .fn("1", "2")
145
+    ).toEqual("hi");
146
+    expect(thirdCounts).toEqual(2);
147
+
148
+    expect(
149
+      uut
150
+        .defgeneric("foobar", "a")
151
+        .primary([Object], function (a) {
152
+          return 1;
153
+        })
154
+        .primary([String], function (a) {
155
+          return 2;
156
+        })
157
+        .fn("foobar")
158
+    ).toEqual(2);
159
+  });
160
+
161
+  test("next-method-p works", () => {
162
+    expect.assertions(3);
163
+
164
+    uut
165
+      .defgeneric("foobar", "a")
166
+      .primary([Object], function (a) {
167
+        expect(this.next_method_p).toBe(false);
168
+      })
169
+      .fn({});
170
+
171
+    uut
172
+      .defgeneric("foobar", "a")
173
+      .primary([Object], function (a) {
174
+        expect(this.next_method_p).toBe(false);
175
+      })
176
+      .primary([String], function (a) {
177
+        expect(this.next_method_p).toBe(true);
178
+      })
179
+      .fn("foobar");
180
+
181
+    uut
182
+      .defgeneric("foobar", "a")
183
+      .primary([Object], function (a) {
184
+        expect(this.next_method_p).toBe(false);
185
+      })
186
+      .primary([String], function (a) {
187
+        expect(this.next_method_p).toBe(true);
188
+      })
189
+      .fn(1);
190
+  });
191
+
192
+  test("call-next-method works", () => {
193
+    try {
194
+      uut
195
+        .defgeneric("foobar", "a")
196
+        .primary([Object], function (a) {
197
+          this.call_next_method();
198
+        })
199
+        .primary([String], function (a) {
200
+          return 1;
201
+        })
202
+        .fn({});
203
+      fail();
204
+    } catch (err) {
205
+      expect(err).toBeInstanceOf(uut.NoNextMethodError);
206
+    }
207
+
208
+    expect(
209
+      uut
210
+        .defgeneric("foobar", "a")
211
+        .primary([Object], function (a) {
212
+          return 1;
213
+        })
214
+        .primary([String], function (a) {
215
+          return this.call_next_method();
216
+        })
217
+        .fn("foobar")
218
+    ).toEqual(1);
219
+
220
+    expect(
221
+      uut
222
+        .defgeneric("foobar", "a", "b")
223
+        .primary([String, String], function (a, b) {
224
+          return `1${this.call_next_method()}`;
225
+        })
226
+        .primary([Object, String], function (a, b) {
227
+          return `3${this.call_next_method()}`;
228
+        })
229
+        .primary([String, Object], function (a, b) {
230
+          return `2${this.call_next_method()}`;
231
+        })
232
+        .primary([Object, Object], function (a, b) {
233
+          return `4`;
234
+        })
235
+        .fn("a", "b")
236
+    ).toEqual("1234");
237
+
238
+    try {
239
+      uut
240
+        .defgeneric("foobar", "a")
241
+        .primary([Object], function (a) {
242
+          this.call_next_method();
243
+        })
244
+        .fn({});
245
+      fail();
246
+    } catch (err) {
247
+      expect(err).toBeInstanceOf(uut.NoNextMethodError);
248
+    }
249
+  });
221 250
 });
222 251
 
223
-describe('custom specializers', () => {
224
-    test('Shape works', () => {
225
-        expect(uut.defgeneric("foobar", "a")
226
-            .primary([uut.Shape('a', 'b')], ({ a, b }) => a + b)
227
-            .primary([Object], _ => null)
228
-            .fn({ a: 1, b: 2 }))
229
-            .toEqual(3);
230
-
231
-        expect(uut.defgeneric("foobar", "a")
232
-            .primary([uut.Shape('a', 'b')], ({ a, b }) => a + b)
233
-            .primary([Object], _ => null)
234
-            .fn({ a: 1, b: 2, c: 3 }))
235
-            .toEqual(3);
236
-
237
-        expect(uut.defgeneric("foobar", "a")
238
-            .primary([uut.Shape('a', 'b')], ({ a, b }) => a + b)
239
-            .primary([Object], _ => null)
240
-            .fn({ a: 1 }))
241
-            .toEqual(null);
242
-
243
-        expect(uut.defgeneric("foobar", "a")
244
-            .primary([uut.Shape(['a', 1], 'b')], ({ a, b }) => a + b)
245
-            .primary([Object], _ => null)
246
-            .fn({ a: 1, b: 3 }))
247
-            .toEqual(4);
248
-
249
-        expect(uut.defgeneric("foobar", "a")
250
-            .primary([uut.Shape(['a', null], 'b')], ({ a, b }) => b)
251
-            .primary([Object], _ => null)
252
-            .fn({ a: null, b: 3 }))
253
-            .toEqual(3);
254
-
255
-        expect(uut.defgeneric("foobar", "a")
256
-            .primary([uut.Shape(['a', undefined], 'b')], ({ a, b }) => b)
257
-            .primary([Object], _ => null)
258
-            .fn({ b: 5 }))
259
-            .toEqual(null); //undefined is not a permissible default: treated as if the key is missing
260
-
261
-        expect(uut.defgeneric("foobar", "a")
262
-            .primary([uut.Shape(['a', 1], 'b')], ({ a, b }) => a + b)
263
-            .primary([Object], _ => null)
264
-            .fn({ a: 2, b: 3 }))
265
-            .toEqual(null);
266
-    });
267
-
268
-    test('Shape, prototype precedence', () => {
269
-        expect(uut.defgeneric("foobar4", "a")
270
-            .primary([uut.Shape('a')], ({ a }) => a)
271
-            .primary([uut.Shape('a', 'b')], ({ a, b }) => { return a + b })
272
-            .primary([Object], _ => null).fn({ a: 1, b: 3 }))
273
-            .toEqual(4);
274
-
275
-        expect(uut.defgeneric("foobar", "a")
276
-            .primary([uut.Shape('a', 'b')], ({ a, b }) => a + b)
277
-            .primary([uut.Shape('b')], ({ b }) => b)
278
-            .primary([Object], _ => null)
279
-            .fn({ a: 1, b: 2 }))
280
-            .toEqual(3);
281
-
282
-        const Foo = function () { }
283
-        Foo.prototype = { a: true, b: null };
284
-        expect(uut.defgeneric("foobar", "a")
285
-            .primary([uut.Shape('a')], function ({ a }) { return `a${this.call_next_method()}`; })
286
-            .primary([uut.Shape('a', 'b', 'c')], function ({ a, b, c }) { return `c${this.call_next_method()}`; })
287
-            .primary([uut.Shape('a', 'b')], function ({ a, b }) { return `b${this.call_next_method()}`; })
288
-            .primary([Object], _ => 'd')
289
-            .fn(Object.assign(new Foo(), { c: 3 })))
290
-            .toEqual('cbad');
291
-    });
252
+describe("custom specializers", () => {
253
+  test("Shape works", () => {
254
+    expect(
255
+      uut
256
+        .defgeneric("foobar", "a")
257
+        .primary([uut.Shape("a", "b")], ({ a, b }) => a + b)
258
+        .primary([Object], _ => null)
259
+        .fn({ a: 1, b: 2 })
260
+    ).toEqual(3);
261
+
262
+    expect(
263
+      uut
264
+        .defgeneric("foobar", "a")
265
+        .primary([uut.Shape("a", "b")], ({ a, b }) => a + b)
266
+        .primary([Object], _ => null)
267
+        .fn({ a: 1, b: 2, c: 3 })
268
+    ).toEqual(3);
269
+
270
+    expect(
271
+      uut
272
+        .defgeneric("foobar", "a")
273
+        .primary([uut.Shape("a", "b")], ({ a, b }) => a + b)
274
+        .primary([Object], _ => null)
275
+        .fn({ a: 1 })
276
+    ).toEqual(null);
277
+
278
+    expect(
279
+      uut
280
+        .defgeneric("foobar", "a")
281
+        .primary([uut.Shape(["a", 1], "b")], ({ a, b }) => a + b)
282
+        .primary([Object], _ => null)
283
+        .fn({ a: 1, b: 3 })
284
+    ).toEqual(4);
285
+
286
+    expect(
287
+      uut
288
+        .defgeneric("foobar", "a")
289
+        .primary([uut.Shape(["a", null], "b")], ({ a, b }) => b)
290
+        .primary([Object], _ => null)
291
+        .fn({ a: null, b: 3 })
292
+    ).toEqual(3);
293
+
294
+    expect(
295
+      uut
296
+        .defgeneric("foobar", "a")
297
+        .primary([uut.Shape(["a", undefined], "b")], ({ a, b }) => b)
298
+        .primary([Object], _ => null)
299
+        .fn({ b: 5 })
300
+    ).toEqual(null); //undefined is not a permissible default: treated as if the key is missing
301
+
302
+    expect(
303
+      uut
304
+        .defgeneric("foobar", "a")
305
+        .primary([uut.Shape(["a", 1], "b")], ({ a, b }) => a + b)
306
+        .primary([Object], _ => null)
307
+        .fn({ a: 2, b: 3 })
308
+    ).toEqual(null);
309
+  });
310
+
311
+  test("Shape, prototype precedence", () => {
312
+    expect(
313
+      uut
314
+        .defgeneric("foobar4", "a")
315
+        .primary([uut.Shape("a")], ({ a }) => a)
316
+        .primary([uut.Shape("a", "b")], ({ a, b }) => {
317
+          return a + b;
318
+        })
319
+        .primary([Object], _ => null)
320
+        .fn({ a: 1, b: 3 })
321
+    ).toEqual(4);
322
+
323
+    expect(
324
+      uut
325
+        .defgeneric("foobar", "a")
326
+        .primary([uut.Shape("a", "b")], ({ a, b }) => a + b)
327
+        .primary([uut.Shape("b")], ({ b }) => b)
328
+        .primary([Object], _ => null)
329
+        .fn({ a: 1, b: 2 })
330
+    ).toEqual(3);
331
+
332
+    const Foo = function () {};
333
+    Foo.prototype = { a: true, b: null };
334
+    expect(
335
+      uut
336
+        .defgeneric("foobar", "a")
337
+        .primary([uut.Shape("a")], function ({ a }) {
338
+          return `a${this.call_next_method()}`;
339
+        })
340
+        .primary([uut.Shape("a", "b", "c")], function ({ a, b, c }) {
341
+          return `c${this.call_next_method()}`;
342
+        })
343
+        .primary([uut.Shape("a", "b")], function ({ a, b }) {
344
+          return `b${this.call_next_method()}`;
345
+        })
346
+        .primary([Object], _ => "d")
347
+        .fn(Object.assign(new Foo(), { c: 3 }))
348
+    ).toEqual("cbad");
349
+  });
292 350
 });
293 351
 
294 352
 describe("Shape", () => {
295
-    test('super_of', () => {
296
-        expect(uut.Shape().super_of(uut.Shape("a", "b", "c"))).toBeTruthy();
297
-        expect(uut.Shape('a').super_of(uut.Shape('a', 'b'))).toBeTruthy();
298
-        expect(uut.Shape("a", "b").super_of(uut.Shape("a", "b", "c"))).toBeTruthy();
299
-        expect(uut.Shape("a", "b").super_of(uut.Shape("a", "b", 3))).toBeTruthy();
300
-        expect(uut.Shape("a", "b").super_of(uut.Shape("a", "b"))).toBeFalsy();
301
-        expect(uut.Shape("a", "b").super_of(uut.Shape("a"))).toBeFalsy();
302
-    });
353
+  test("super_of", () => {
354
+    expect(uut.Shape().super_of(uut.Shape("a", "b", "c"))).toBeTruthy();
355
+    expect(uut.Shape("a").super_of(uut.Shape("a", "b"))).toBeTruthy();
356
+    expect(uut.Shape("a", "b").super_of(uut.Shape("a", "b", "c"))).toBeTruthy();
357
+    expect(uut.Shape("a", "b").super_of(uut.Shape("a", "b", 3))).toBeTruthy();
358
+    expect(uut.Shape("a", "b").super_of(uut.Shape("a", "b"))).toBeFalsy();
359
+    expect(uut.Shape("a", "b").super_of(uut.Shape("a"))).toBeFalsy();
360
+  });
303 361
 });
... ...
@@ -1,109 +1,102 @@
1 1
 /* eslint-disable */
2
-import {GenericFunction, around_qualifier} from '../src/genfuns';
2
+import { GenericFunction, around_qualifier } from "../src/genfuns";
3 3
 
4 4
 function zipWith(fn, ...args) {
5
-    const minLen = Math.min(...args.map(x => x.length));
6
-    const res = [];
5
+  const minLen = Math.min(...args.map(x => x.length));
6
+  const res = [];
7 7
 
8
-    for (let x = 0; x < minLen; x++) {
9
-        res.push(fn(...args.map(a => a[x])));
10
-    }
8
+  for (let x = 0; x < minLen; x++) {
9
+    res.push(fn(...args.map(a => a[x])));
10
+  }
11 11
 
12
-    return res;
12
+  return res;
13 13
 }
14 14
 
15
-const gf = GenericFunction(
16
-    "foobar", ["a", "b"]
17
-).before(
18
-    [Object, Array], function (a,b) {console.log('in before', this.next_method_p);} 
19
-).primary(
20
-    [Object, Array], function (a,b) {
21
-        console.info('next_result: ', this.call_next_method(), this.next_method_p);
22
-        return [a,...b];
23
-    } 
24
-).primary(
25
-    [Object, Object], function (thing, single) {
26
-        console.log("hello from previous method", this.next_method_p);
27
-        return [thing, single];
28
-    }
29
-).after(
30
-    [Number, Array], function (a,b) {console.log(`in after for ${a}`, this.next_method_p);} 
31
-).fn;
15
+const gf = GenericFunction("foobar", ["a", "b"])
16
+  .before([Object, Array], function (a, b) {
17
+    console.log("in before", this.next_method_p);
18
+  })
19
+  .primary([Object, Array], function (a, b) {
20
+    console.info("next_result: ", this.call_next_method(), this.next_method_p);
21
+    return [a, ...b];
22
+  })
23
+  .primary([Object, Object], function (thing, single) {
24
+    console.log("hello from previous method", this.next_method_p);
25
+    return [thing, single];
26
+  })
27
+  .after([Number, Array], function (a, b) {
28
+    console.log(`in after for ${a}`, this.next_method_p);
29
+  }).fn;
32 30
 
33 31
 function groupGFMessages(gf) {
34
-    return gf.method([around_qualifier], [Object,Object], function(a,b) {
35
-        console.groupCollapsed(gf.name);
36
-        try {
37
-            return this.call_next_method();
38
-        } finally {
39
-            console.groupEnd();
40
-        }
41
-    })
32
+  return gf.method([around_qualifier], [Object, Object], function (a, b) {
33
+    console.groupCollapsed(gf.name);
34
+    try {
35
+      return this.call_next_method();
36
+    } finally {
37
+      console.groupEnd();
38
+    }
39
+  });
42 40
 }
43 41
 
44 42
 groupGFMessages(gf.gf);
45 43
 
46
-console.log(gf(2,["asdf"]));
44
+console.log(gf(2, ["asdf"]));
47 45
 
48
-const gf2 = GenericFunction(
49
-    "another", ["a"]
50
-).primary(
51
-    [Object], function (a) { return {value: a}; }
52
-).method(
53
-    [around_qualifier], [Number], function(thing) {
54
-        console.log('before next method in number around');
55
-        const val = this.call_next_method();
56
-        console.log('after next method in number around', val);
57
-        return {was_num: true, ...val};
58
-    }
59
-).method(
60
-    [around_qualifier], [Object], function(thing) {
61
-        console.log('before next method in generic around');
62
-        const val = this.call_next_method();
63
-        console.log('after next method in generic around', val);
64
-        return {was_obj: true, ...val};
65
-    }
66
-);
46
+const gf2 = GenericFunction("another", ["a"])
47
+  .primary([Object], function (a) {
48
+    return { value: a };
49
+  })
50
+  .method([around_qualifier], [Number], function (thing) {
51
+    console.log("before next method in number around");
52
+    const val = this.call_next_method();
53
+    console.log("after next method in number around", val);
54
+    return { was_num: true, ...val };
55
+  })
56
+  .method([around_qualifier], [Object], function (thing) {
57
+    console.log("before next method in generic around");
58
+    const val = this.call_next_method();
59
+    console.log("after next method in generic around", val);
60
+    return { was_obj: true, ...val };
61
+  });
67 62
 
68 63
 function MyStore() {
69
-    this.name = 'foo';
70
-    this.address = '1234 asdfadfd'
64
+  this.name = "foo";
65
+  this.address = "1234 asdfadfd";
71 66
 }
72 67
 
73
-class NameField extends HTMLElement {constructor() {
74
-    super()
75
-    const style = document.createElement('style');
68
+class NameField extends HTMLElement {
69
+  constructor() {
70
+    super();
71
+    const style = document.createElement("style");
76 72
     this.appendChild(style);
77
-}}
78
-customElements.define('the-name', NameField);
73
+  }
74
+}
75
+customElements.define("the-name", NameField);
79 76
 
80 77
 class AddressField extends HTMLElement {
81
-    constructor() { super() }
78
+  constructor() {
79
+    super();
80
+  }
82 81
 }
83
-customElements.define('the-address', AddressField);
82
+customElements.define("the-address", AddressField);
84 83
 
85
-const renderFn = defgeneric(
86
-    "dorender", ["component", "el"]
87
-).primary(
88
-    [MyStore, NameField], function (comp, heading) {
89
-        console.log('heading el', this.next_method_p);
90
-        heading.textContent = comp.name;
91
-    }
92
-).primary(
93
-    [MyStore, AddressField], function (comp, el) {
94
-        console.log('address el', this.next_method_p);
95
-        el.textContent = comp.address;
96
-    }
97
-).primary(
98
-    [MyStore, HTMLElement], function (comp, el) {
99
-        console.log('HtmlElement el ', el, this.next_method_p);
100
-        renderFn.fn(comp, el.querySelector('the-name'));
101
-        renderFn.fn(comp, el.querySelector('the-address'));
102
-    }
103
-).before(
104
-    [Object, HTMLElement], function (_, el) {
105
-        console.log('has next? ', this.next_method_p)
106
-    }
107
-);
84
+const renderFn = defgeneric("dorender", ["component", "el"])
85
+  .primary([MyStore, NameField], function (comp, heading) {
86
+    console.log("heading el", this.next_method_p);
87
+    heading.textContent = comp.name;
88
+  })
89
+  .primary([MyStore, AddressField], function (comp, el) {
90
+    console.log("address el", this.next_method_p);
91
+    el.textContent = comp.address;
92
+  })
93
+  .primary([MyStore, HTMLElement], function (comp, el) {
94
+    console.log("HtmlElement el ", el, this.next_method_p);
95
+    renderFn.fn(comp, el.querySelector("the-name"));
96
+    renderFn.fn(comp, el.querySelector("the-address"));
97
+  })
98
+  .before([Object, HTMLElement], function (_, el) {
99
+    console.log("has next? ", this.next_method_p);
100
+  });
108 101
 
109
-renderFn.fn(new MyStore(), document.querySelector('section'));
102
+renderFn.fn(new MyStore(), document.querySelector("section"));