@rulecad/variables 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -3
- package/variables.d.mts +73 -0
- package/variables.mjs +23 -0
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulecad/variables",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Design values you can trace: every number says where it comes from, and expressions are parsed, never run.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"exports":
|
|
6
|
+
"exports": {
|
|
7
|
+
"types": "./variables.d.mts",
|
|
8
|
+
"default": "./variables.mjs"
|
|
9
|
+
},
|
|
7
10
|
"files": [
|
|
8
11
|
"variables.mjs",
|
|
12
|
+
"variables.d.mts",
|
|
9
13
|
"README.md",
|
|
10
14
|
"LICENSE"
|
|
11
15
|
],
|
|
@@ -28,5 +32,6 @@
|
|
|
28
32
|
},
|
|
29
33
|
"scripts": {
|
|
30
34
|
"test": "node --test"
|
|
31
|
-
}
|
|
35
|
+
},
|
|
36
|
+
"types": "./variables.d.mts"
|
|
32
37
|
}
|
package/variables.d.mts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export function checkName(name: any, d: any, v: any): string;
|
|
2
|
+
/**
|
|
3
|
+
* One expression: + - * / and brackets, min, max, round, sind, cosd, tand, over numbers and names. Never runs code.
|
|
4
|
+
* @param {string | number} src
|
|
5
|
+
* @param {(name: string) => number} lookup the value of a name
|
|
6
|
+
* @returns {number}
|
|
7
|
+
*/
|
|
8
|
+
export function evaluate(src: string | number, lookup: (name: string) => number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Every variable's value, and an entry for each variable and rule for checks and rule cards.
|
|
11
|
+
* @param {DesignObject} object
|
|
12
|
+
* @param {{ sets?: Record<string, RuleSet>, set?: Record<string, number | string>, display?: Record<string, number | string>, load?: (name: string) => RuleSet }} [options]
|
|
13
|
+
* @returns {{ values: Record<string, any>, entries: Entry[] }}
|
|
14
|
+
*/
|
|
15
|
+
export function resolve(object: DesignObject, { sets, set, display, load }?: {
|
|
16
|
+
sets?: Record<string, RuleSet>;
|
|
17
|
+
set?: Record<string, number | string>;
|
|
18
|
+
display?: Record<string, number | string>;
|
|
19
|
+
load?: (name: string) => RuleSet;
|
|
20
|
+
}): {
|
|
21
|
+
values: Record<string, any>;
|
|
22
|
+
entries: Entry[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Number literals in a design's code other than 0, 1 and 2 (outside comments and strings).
|
|
26
|
+
* @param {string} source
|
|
27
|
+
* @returns {{ line: number, text: string }[]}
|
|
28
|
+
*/
|
|
29
|
+
export function lint(source: string): {
|
|
30
|
+
line: number;
|
|
31
|
+
text: string;
|
|
32
|
+
}[];
|
|
33
|
+
/** @typedef {{ value: number | string, unit?: string, rule?: string, kind?: 'spec' | 'community' | 'default' | 'estimate' | 'measured', source?: string, checked?: string, label?: string, show?: boolean, interface?: boolean, tweak?: { min: number, max: number }, choice?: string[], type?: 'text' | 'anchor' | 'layout' }} Variable */
|
|
34
|
+
/** @typedef {{ name?: string, rules: Record<string, Variable> }} RuleSet */
|
|
35
|
+
/** @typedef {{ uses?: string[], variables?: Record<string, Variable>, [field: string]: any }} DesignObject */
|
|
36
|
+
/** @typedef {{ name: string, value: number | string, used?: boolean, set?: boolean, [field: string]: any }} Entry */
|
|
37
|
+
export const ANCHORS: string[];
|
|
38
|
+
export function isName(d: any): boolean;
|
|
39
|
+
export function options(d: any): any;
|
|
40
|
+
export function fmt(n: number | string): string;
|
|
41
|
+
export type Variable = {
|
|
42
|
+
value: number | string;
|
|
43
|
+
unit?: string;
|
|
44
|
+
rule?: string;
|
|
45
|
+
kind?: "spec" | "community" | "default" | "estimate" | "measured";
|
|
46
|
+
source?: string;
|
|
47
|
+
checked?: string;
|
|
48
|
+
label?: string;
|
|
49
|
+
show?: boolean;
|
|
50
|
+
interface?: boolean;
|
|
51
|
+
tweak?: {
|
|
52
|
+
min: number;
|
|
53
|
+
max: number;
|
|
54
|
+
};
|
|
55
|
+
choice?: string[];
|
|
56
|
+
type?: "text" | "anchor" | "layout";
|
|
57
|
+
};
|
|
58
|
+
export type RuleSet = {
|
|
59
|
+
name?: string;
|
|
60
|
+
rules: Record<string, Variable>;
|
|
61
|
+
};
|
|
62
|
+
export type DesignObject = {
|
|
63
|
+
uses?: string[];
|
|
64
|
+
variables?: Record<string, Variable>;
|
|
65
|
+
[field: string]: any;
|
|
66
|
+
};
|
|
67
|
+
export type Entry = {
|
|
68
|
+
name: string;
|
|
69
|
+
value: number | string;
|
|
70
|
+
used?: boolean;
|
|
71
|
+
set?: boolean;
|
|
72
|
+
[field: string]: any;
|
|
73
|
+
};
|
package/variables.mjs
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
// No imports and no file access: it runs in a browser as well. Rule sets are handed in (sets) or fetched by name
|
|
8
8
|
// through load(name), such as one that reads rules/<name>.json.
|
|
9
9
|
|
|
10
|
+
/** @typedef {{ value: number | string, unit?: string, rule?: string, kind?: 'spec' | 'community' | 'default' | 'estimate' | 'measured', source?: string, checked?: string, label?: string, show?: boolean, interface?: boolean, tweak?: { min: number, max: number }, choice?: string[], type?: 'text' | 'anchor' | 'layout' }} Variable */
|
|
11
|
+
/** @typedef {{ name?: string, rules: Record<string, Variable> }} RuleSet */
|
|
12
|
+
/** @typedef {{ uses?: string[], variables?: Record<string, Variable>, [field: string]: any }} DesignObject */
|
|
13
|
+
/** @typedef {{ name: string, value: number | string, used?: boolean, set?: boolean, [field: string]: any }} Entry */
|
|
14
|
+
|
|
10
15
|
export const ANCHORS = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'];
|
|
11
16
|
// A variable that holds a name or text, and the names it may hold (null: any text)
|
|
12
17
|
export const isName = (d) => !!(d.choice || ['text', 'anchor', 'layout'].includes(d.type));
|
|
@@ -35,6 +40,12 @@ function tokens(src) {
|
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
// evaluate("line * 3", lookup) -> number. lookup(name) gives a name's value.
|
|
43
|
+
/**
|
|
44
|
+
* One expression: + - * / and brackets, min, max, round, sind, cosd, tand, over numbers and names. Never runs code.
|
|
45
|
+
* @param {string | number} src
|
|
46
|
+
* @param {(name: string) => number} lookup the value of a name
|
|
47
|
+
* @returns {number}
|
|
48
|
+
*/
|
|
38
49
|
export function evaluate(src, lookup) {
|
|
39
50
|
if (typeof src === 'number') return src;
|
|
40
51
|
const t = tokens(String(src));
|
|
@@ -79,6 +90,12 @@ export function evaluate(src, lookup) {
|
|
|
79
90
|
// { "type": "text", "value": "", "max": 8 } free text, e.g. a keycap's legend
|
|
80
91
|
// { "type": "anchor", "value": "mc" } one of 9 places on a face: tl tc tr, ml mc mr, bl bc br
|
|
81
92
|
// { "type": "layout", "value": "grid", "choice": [...] } a layout file in the project's layouts/ (or a built-in)
|
|
93
|
+
/**
|
|
94
|
+
* Every variable's value, and an entry for each variable and rule for checks and rule cards.
|
|
95
|
+
* @param {DesignObject} object
|
|
96
|
+
* @param {{ sets?: Record<string, RuleSet>, set?: Record<string, number | string>, display?: Record<string, number | string>, load?: (name: string) => RuleSet }} [options]
|
|
97
|
+
* @returns {{ values: Record<string, any>, entries: Entry[] }}
|
|
98
|
+
*/
|
|
82
99
|
export function resolve(object, { sets = {}, set = {}, display = {}, load } = {}) {
|
|
83
100
|
const ruleSets = Object.fromEntries((object.uses || []).map((u) => {
|
|
84
101
|
const s = sets[u] || (load ? load(u) : null);
|
|
@@ -134,10 +151,16 @@ export function resolve(object, { sets = {}, set = {}, display = {}, load } = {}
|
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
// Round for display: at most 2 decimals, no trailing zeros.
|
|
154
|
+
/** A number to two decimals at most; a name as it is. @param {number | string} n @returns {string} */
|
|
137
155
|
export const fmt = (n) => (typeof n === 'number' ? String(Number(n.toFixed(2))) : String(n)); // choices are names
|
|
138
156
|
|
|
139
157
|
// lint(source) -> [{ line, text }]: number literals in a design's code that should be variables. Every measurement
|
|
140
158
|
// belongs in a variable that says where it comes from; only 0, 1 and 2 (and numbers in comments and strings) pass.
|
|
159
|
+
/**
|
|
160
|
+
* Number literals in a design's code other than 0, 1 and 2 (outside comments and strings).
|
|
161
|
+
* @param {string} source
|
|
162
|
+
* @returns {{ line: number, text: string }[]}
|
|
163
|
+
*/
|
|
141
164
|
export function lint(source) {
|
|
142
165
|
const code = source.replace(/\/\*[\s\S]*?\*\//g, (m) => m.replace(/[^\n]/g, ' ')).replace(/\/\/.*$/gm, '')
|
|
143
166
|
.replace(/(['"`])(?:\\.|(?!\1).)*\1/g, (m) => m.replace(/./g, ' '));
|