@cruba/crubal 0.0.0-stage → 0.2.0
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/LICENSE +202 -0
- package/README.md +97 -2
- package/dist/bin/crubal.d.ts +2 -0
- package/dist/bin/crubal.js +103 -0
- package/dist/bin/crubal.js.map +1 -0
- package/dist/src/access.d.ts +126 -0
- package/dist/src/access.js +517 -0
- package/dist/src/access.js.map +1 -0
- package/dist/src/arrival.d.ts +55 -0
- package/dist/src/arrival.js +124 -0
- package/dist/src/arrival.js.map +1 -0
- package/dist/src/browser.d.ts +10 -0
- package/dist/src/browser.js +13 -0
- package/dist/src/browser.js.map +1 -0
- package/dist/src/bundle.d.ts +66 -0
- package/dist/src/bundle.js +753 -0
- package/dist/src/bundle.js.map +1 -0
- package/dist/src/canonical.d.ts +6 -0
- package/dist/src/canonical.js +47 -0
- package/dist/src/canonical.js.map +1 -0
- package/dist/src/conditions.d.ts +28 -0
- package/dist/src/conditions.js +216 -0
- package/dist/src/conditions.js.map +1 -0
- package/dist/src/corpus.d.ts +8 -0
- package/dist/src/corpus.js +1207 -0
- package/dist/src/corpus.js.map +1 -0
- package/dist/src/defs.d.ts +151 -0
- package/dist/src/defs.js +611 -0
- package/dist/src/defs.js.map +1 -0
- package/dist/src/dictionary.d.ts +65 -0
- package/dist/src/dictionary.js +557 -0
- package/dist/src/dictionary.js.map +1 -0
- package/dist/src/exchange.d.ts +236 -0
- package/dist/src/exchange.js +1035 -0
- package/dist/src/exchange.js.map +1 -0
- package/dist/src/forms.d.ts +16 -0
- package/dist/src/forms.js +169 -0
- package/dist/src/forms.js.map +1 -0
- package/dist/src/index.d.ts +27 -0
- package/dist/src/index.js +29 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lex.d.ts +21 -0
- package/dist/src/lex.js +142 -0
- package/dist/src/lex.js.map +1 -0
- package/dist/src/lifecycle.d.ts +84 -0
- package/dist/src/lifecycle.js +415 -0
- package/dist/src/lifecycle.js.map +1 -0
- package/dist/src/log.d.ts +78 -0
- package/dist/src/log.js +506 -0
- package/dist/src/log.js.map +1 -0
- package/dist/src/migrate.d.ts +111 -0
- package/dist/src/migrate.js +286 -0
- package/dist/src/migrate.js.map +1 -0
- package/dist/src/model.d.ts +68 -0
- package/dist/src/model.js +188 -0
- package/dist/src/model.js.map +1 -0
- package/dist/src/packages.d.ts +69 -0
- package/dist/src/packages.js +232 -0
- package/dist/src/packages.js.map +1 -0
- package/dist/src/print-text.d.ts +7 -0
- package/dist/src/print-text.js +216 -0
- package/dist/src/print-text.js.map +1 -0
- package/dist/src/publish.d.ts +27 -0
- package/dist/src/publish.js +275 -0
- package/dist/src/publish.js.map +1 -0
- package/dist/src/read-text.d.ts +10 -0
- package/dist/src/read-text.js +385 -0
- package/dist/src/read-text.js.map +1 -0
- package/dist/src/records.d.ts +31 -0
- package/dist/src/records.js +72 -0
- package/dist/src/records.js.map +1 -0
- package/dist/src/review.d.ts +22 -0
- package/dist/src/review.js +198 -0
- package/dist/src/review.js.map +1 -0
- package/dist/src/rules.d.ts +96 -0
- package/dist/src/rules.js +611 -0
- package/dist/src/rules.js.map +1 -0
- package/dist/src/schedule.d.ts +24 -0
- package/dist/src/schedule.js +126 -0
- package/dist/src/schedule.js.map +1 -0
- package/dist/src/std-packages.d.ts +9 -0
- package/dist/src/std-packages.js +268 -0
- package/dist/src/std-packages.js.map +1 -0
- package/dist/src/store.d.ts +164 -0
- package/dist/src/store.js +538 -0
- package/dist/src/store.js.map +1 -0
- package/dist/src/tree.d.ts +35 -0
- package/dist/src/tree.js +159 -0
- package/dist/src/tree.js.map +1 -0
- package/dist/src/units-table.d.ts +1 -0
- package/dist/src/units-table.js +200 -0
- package/dist/src/units-table.js.map +1 -0
- package/dist/src/units.d.ts +42 -0
- package/dist/src/units.js +98 -0
- package/dist/src/units.js.map +1 -0
- package/dist/src/views.d.ts +216 -0
- package/dist/src/views.js +761 -0
- package/dist/src/views.js.map +1 -0
- package/package.json +60 -4
package/dist/src/tree.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// tree.ts: the text form's lines (spec chapter 2.1), read into a tree of nodes without knowing what any
|
|
2
|
+
// key means. Comments are stripped, tabs in indentation are refused, and a line belongs inside the nearest
|
|
3
|
+
// earlier line that is indented less.
|
|
4
|
+
export class CrubalError extends Error {
|
|
5
|
+
line;
|
|
6
|
+
constructor(message, line) {
|
|
7
|
+
super(line ? `line ${line}: ${message}` : message);
|
|
8
|
+
this.name = "CrubalError";
|
|
9
|
+
this.line = line;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Remove a `//` comment that starts the line or follows white space, outside quotes. */
|
|
13
|
+
export function stripComment(line) {
|
|
14
|
+
let quoted = false;
|
|
15
|
+
for (let i = 0; i < line.length; i++) {
|
|
16
|
+
const ch = line[i];
|
|
17
|
+
if (quoted && ch === "\\") {
|
|
18
|
+
i++;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (ch === '"')
|
|
22
|
+
quoted = !quoted;
|
|
23
|
+
if (!quoted && ch === "/" && line[i + 1] === "/" && (i === 0 || /\s/.test(line[i - 1] ?? ""))) {
|
|
24
|
+
return line.slice(0, i).trimEnd();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return line.trimEnd();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Split a line into a pair at the separator (spec 2.1): the first `: ` (colon then space), or a colon at
|
|
31
|
+
* the end of the line. A colon inside quotes never separates.
|
|
32
|
+
*/
|
|
33
|
+
export function splitPair(text) {
|
|
34
|
+
let quoted = false;
|
|
35
|
+
for (let i = 0; i < text.length; i++) {
|
|
36
|
+
const ch = text[i];
|
|
37
|
+
if (quoted && ch === "\\") {
|
|
38
|
+
i++;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (ch === '"')
|
|
42
|
+
quoted = !quoted;
|
|
43
|
+
if (quoted || ch !== ":")
|
|
44
|
+
continue;
|
|
45
|
+
if (i === text.length - 1)
|
|
46
|
+
return i > 0 ? { key: text.slice(0, i), value: "" } : null;
|
|
47
|
+
if (text[i + 1] === " ") {
|
|
48
|
+
const key = text.slice(0, i);
|
|
49
|
+
if (!key || /\s/.test(key))
|
|
50
|
+
return null;
|
|
51
|
+
return { key, value: text.slice(i + 2).trim() };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function lineNode(body, line, indent) {
|
|
57
|
+
const pair = splitPair(body);
|
|
58
|
+
if (pair)
|
|
59
|
+
return { kind: "pair", key: pair.key, value: pair.value, text: body, line, indent, children: [] };
|
|
60
|
+
return { kind: "line", key: null, value: body, text: body, line, indent, children: [] };
|
|
61
|
+
}
|
|
62
|
+
/** The lines inside a node, as written: each with its indentation relative to the first, comments removed. */
|
|
63
|
+
export function innerText(node) {
|
|
64
|
+
const lines = [];
|
|
65
|
+
const seen = new Set();
|
|
66
|
+
const walk = (n) => {
|
|
67
|
+
for (const c of n.children) {
|
|
68
|
+
if (!seen.has(c.line)) {
|
|
69
|
+
seen.add(c.line);
|
|
70
|
+
lines.push({ indent: c.indent, text: c.text, line: c.line });
|
|
71
|
+
}
|
|
72
|
+
walk(c);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
walk(node);
|
|
76
|
+
lines.sort((a, b) => a.line - b.line);
|
|
77
|
+
const base = lines[0]?.indent ?? 0;
|
|
78
|
+
return lines.map((l) => " ".repeat(Math.max(0, l.indent - base)) + l.text).join("\n");
|
|
79
|
+
}
|
|
80
|
+
/** Read text into a tree of nodes. */
|
|
81
|
+
export function readTree(source) {
|
|
82
|
+
const root = { kind: "line", key: null, value: "", text: "", line: 0, indent: -1, children: [] };
|
|
83
|
+
const stack = [{ node: root, indent: -1 }];
|
|
84
|
+
const lines = source.replace(/^/, "").split(/\r?\n/);
|
|
85
|
+
// A long-text block (2.4.1): after `key: |`, every line indented more than the key is the text, taken raw
|
|
86
|
+
// (no comment, indentation kept relative to the first line); a line holding only `|` is an empty line.
|
|
87
|
+
let block = null;
|
|
88
|
+
const closeBlock = () => {
|
|
89
|
+
if (!block)
|
|
90
|
+
return;
|
|
91
|
+
while (block.lines.length && block.lines[block.lines.length - 1] === "")
|
|
92
|
+
block.lines.pop();
|
|
93
|
+
block.node.value = block.lines.join("\n");
|
|
94
|
+
block = null;
|
|
95
|
+
};
|
|
96
|
+
lines.forEach((raw, i) => {
|
|
97
|
+
const line = i + 1;
|
|
98
|
+
if (block) {
|
|
99
|
+
const trimmed = raw.trim();
|
|
100
|
+
const indent = raw.length - raw.trimStart().length;
|
|
101
|
+
if (trimmed === "" || indent > block.indent) {
|
|
102
|
+
if (trimmed === "") {
|
|
103
|
+
block.lines.push("");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (/^ *\t/.test(raw))
|
|
107
|
+
throw new CrubalError("indent with spaces, not tabs", line);
|
|
108
|
+
if (block.base === null)
|
|
109
|
+
block.base = indent;
|
|
110
|
+
block.lines.push(trimmed === "|" ? "" : raw.slice(Math.min(block.base, indent)));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
closeBlock();
|
|
114
|
+
}
|
|
115
|
+
if (/^ *\t/.test(raw))
|
|
116
|
+
throw new CrubalError("indent with spaces, not tabs", line);
|
|
117
|
+
const stripped = stripComment(raw);
|
|
118
|
+
if (!stripped.trim())
|
|
119
|
+
return;
|
|
120
|
+
let indent = stripped.length - stripped.trimStart().length;
|
|
121
|
+
let body = stripped.trim();
|
|
122
|
+
while (stack.length > 1 && (stack.at(-1)?.indent ?? -1) >= indent)
|
|
123
|
+
stack.pop();
|
|
124
|
+
const parent = stack.at(-1)?.node ?? root;
|
|
125
|
+
if (body === "-" || body.startsWith("- ")) {
|
|
126
|
+
const item = { kind: "item", key: null, value: "", text: body, line, indent, children: [] };
|
|
127
|
+
parent.children.push(item);
|
|
128
|
+
stack.push({ node: item, indent });
|
|
129
|
+
const rest = body.slice(1).trimStart();
|
|
130
|
+
if (!rest)
|
|
131
|
+
return;
|
|
132
|
+
// The item's own text: a pair starts the item's first child, so lines indented to its column join
|
|
133
|
+
// the same item; anything else is the item's value.
|
|
134
|
+
indent += stripped.trimStart().indexOf(rest, 1);
|
|
135
|
+
body = rest;
|
|
136
|
+
const first = lineNode(body, line, indent);
|
|
137
|
+
if (first.kind === "line" || body.startsWith("[")) {
|
|
138
|
+
item.value = body;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
item.children.push(first);
|
|
142
|
+
stack.push({ node: first, indent });
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const node = lineNode(body, line, indent);
|
|
146
|
+
parent.children.push(node);
|
|
147
|
+
stack.push({ node, indent });
|
|
148
|
+
const pipe = node.kind === "pair" ? node.value.match(/^\|(?:\s+(\[.*\]))?$/) : null;
|
|
149
|
+
if (pipe) {
|
|
150
|
+
node.block = true;
|
|
151
|
+
if (pipe[1])
|
|
152
|
+
node.detail = pipe[1];
|
|
153
|
+
block = { node, indent, base: null, lines: [] };
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
closeBlock();
|
|
157
|
+
return root.children;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const STANDARD_UNITS = "// The units table's records (11.9). The base unit of each dimension has factor 1 and states the rounding a\n// conversion keeps when the facet states none.\ncrubal: 2\npackage: crubal.com/units /2026-10-15\nowner: crubal.com\n\nmeasure: s\n dimension: time\n factor: 1\n rounding: 3\n spellings: sec, secs, second, seconds\n uncefact: SEC\nmeasure: min\n dimension: time\n factor: 60\n spellings: MIN., mins, minute, minutes\n uncefact: MIN\nmeasure: h\n dimension: time\n factor: 3600\n spellings: hr, hrs, hour, hours\n uncefact: HUR\nmeasure: d\n dimension: time\n factor: 86400\n spellings: day, days\n uncefact: DAY\n\nmeasure: m\n dimension: length\n factor: 1\n rounding: 4\n spellings: meter, meters, metre, metres\n uncefact: MTR\nmeasure: mm\n dimension: length\n factor: 0.001\n uncefact: MMT\nmeasure: cm\n dimension: length\n factor: 0.01\n uncefact: CMT\nmeasure: km\n dimension: length\n factor: 1000\n uncefact: KMT\nmeasure: in\n dimension: length\n factor: 0.0254\n spellings: inch, inches\n uncefact: INH\nmeasure: ft\n dimension: length\n factor: 0.3048\n spellings: foot, feet\n uncefact: FOT\nmeasure: mi\n dimension: length\n factor: 1609.344\n spellings: mile, miles\n uncefact: SMI\n\nmeasure: kg\n dimension: mass\n factor: 1\n rounding: 4\n spellings: kilogram, kilograms\n uncefact: KGM\nmeasure: g\n dimension: mass\n factor: 0.001\n spellings: gram, grams\n uncefact: GRM\nmeasure: oz\n dimension: mass\n factor: 0.028349523125\n spellings: ounce, ounces\n uncefact: ONZ\nmeasure: lb\n dimension: mass\n factor: 0.45359237\n spellings: lbs, pound, pounds\n uncefact: LBR\n\nmeasure: L\n dimension: volume\n factor: 1\n rounding: 3\n spellings: l, liter, liters, litre, litres\n uncefact: LTR\nmeasure: mL\n dimension: volume\n factor: 0.001\n spellings: ml, milliliter, milliliters, millilitre, millilitres\n uncefact: MLT\nmeasure: floz\n dimension: volume\n factor: 0.0295735295625\n spellings: fl oz, fl. oz., fluid ounce, fluid ounces\n uncefact: OZA\nmeasure: gal\n dimension: volume\n factor: 3.785411784\n spellings: gallon, gallons\n uncefact: GLL\n\nmeasure: m2\n dimension: area\n factor: 1\n rounding: 4\n spellings: m\u00B2, sqm, square meter, square meters\n uncefact: MTK\nmeasure: ft2\n dimension: area\n factor: 0.09290304\n spellings: ft\u00B2, sqft, square foot, square feet\n uncefact: FTK\n\nmeasure: K\n dimension: temperature\n factor: 1\n rounding: 2\n spellings: kelvin\n uncefact: KEL\nmeasure: \u00B0C\n dimension: temperature\n factor: 1\n offset: 273.15\n spellings: C, degC, celsius\n uncefact: CEL\nmeasure: \u00B0F\n dimension: temperature\n factor: 0.5555555555555556\n offset: 255.37222222222223\n spellings: F, degF, fahrenheit\n uncefact: FAH\n\nmeasure: B\n dimension: data\n factor: 1\n rounding: 0\n spellings: byte, bytes\n uncefact: AD\nmeasure: KB\n dimension: data\n factor: 1000\n uncefact: 2P\nmeasure: MB\n dimension: data\n factor: 1000000\n uncefact: 4L\nmeasure: GB\n dimension: data\n factor: 1000000000\n uncefact: E34\nmeasure: TB\n dimension: data\n factor: 1000000000000\n uncefact: E35\n\nmeasure: each\n dimension: count\n factor: 1\n rounding: 0\n spellings: ea, pc, pcs, piece, pieces\n uncefact: EA\nmeasure: dozen\n dimension: count\n factor: 12\n spellings: dz, doz\n uncefact: DZN\n\ncurrency: USD\n name: US dollar\n places: 2\ncurrency: EUR\n name: Euro\n places: 2\ncurrency: GBP\n name: Pound sterling\n places: 2\ncurrency: CAD\n name: Canadian dollar\n places: 2\ncurrency: AUD\n name: Australian dollar\n places: 2\ncurrency: MXN\n name: Mexican peso\n places: 2\ncurrency: JPY\n name: Yen\n places: 0\ncurrency: BHD\n name: Bahraini dinar\n places: 3\n";
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// units-table.ts: the standard units table, crubal.com/units, as published in std/units/units.crubal. Generated by
|
|
2
|
+
// `npm run embed` in packages/crubal; a test refuses a copy that has drifted from the file.
|
|
3
|
+
export const STANDARD_UNITS = `// The units table's records (11.9). The base unit of each dimension has factor 1 and states the rounding a
|
|
4
|
+
// conversion keeps when the facet states none.
|
|
5
|
+
crubal: 2
|
|
6
|
+
package: crubal.com/units /2026-10-15
|
|
7
|
+
owner: crubal.com
|
|
8
|
+
|
|
9
|
+
measure: s
|
|
10
|
+
dimension: time
|
|
11
|
+
factor: 1
|
|
12
|
+
rounding: 3
|
|
13
|
+
spellings: sec, secs, second, seconds
|
|
14
|
+
uncefact: SEC
|
|
15
|
+
measure: min
|
|
16
|
+
dimension: time
|
|
17
|
+
factor: 60
|
|
18
|
+
spellings: MIN., mins, minute, minutes
|
|
19
|
+
uncefact: MIN
|
|
20
|
+
measure: h
|
|
21
|
+
dimension: time
|
|
22
|
+
factor: 3600
|
|
23
|
+
spellings: hr, hrs, hour, hours
|
|
24
|
+
uncefact: HUR
|
|
25
|
+
measure: d
|
|
26
|
+
dimension: time
|
|
27
|
+
factor: 86400
|
|
28
|
+
spellings: day, days
|
|
29
|
+
uncefact: DAY
|
|
30
|
+
|
|
31
|
+
measure: m
|
|
32
|
+
dimension: length
|
|
33
|
+
factor: 1
|
|
34
|
+
rounding: 4
|
|
35
|
+
spellings: meter, meters, metre, metres
|
|
36
|
+
uncefact: MTR
|
|
37
|
+
measure: mm
|
|
38
|
+
dimension: length
|
|
39
|
+
factor: 0.001
|
|
40
|
+
uncefact: MMT
|
|
41
|
+
measure: cm
|
|
42
|
+
dimension: length
|
|
43
|
+
factor: 0.01
|
|
44
|
+
uncefact: CMT
|
|
45
|
+
measure: km
|
|
46
|
+
dimension: length
|
|
47
|
+
factor: 1000
|
|
48
|
+
uncefact: KMT
|
|
49
|
+
measure: in
|
|
50
|
+
dimension: length
|
|
51
|
+
factor: 0.0254
|
|
52
|
+
spellings: inch, inches
|
|
53
|
+
uncefact: INH
|
|
54
|
+
measure: ft
|
|
55
|
+
dimension: length
|
|
56
|
+
factor: 0.3048
|
|
57
|
+
spellings: foot, feet
|
|
58
|
+
uncefact: FOT
|
|
59
|
+
measure: mi
|
|
60
|
+
dimension: length
|
|
61
|
+
factor: 1609.344
|
|
62
|
+
spellings: mile, miles
|
|
63
|
+
uncefact: SMI
|
|
64
|
+
|
|
65
|
+
measure: kg
|
|
66
|
+
dimension: mass
|
|
67
|
+
factor: 1
|
|
68
|
+
rounding: 4
|
|
69
|
+
spellings: kilogram, kilograms
|
|
70
|
+
uncefact: KGM
|
|
71
|
+
measure: g
|
|
72
|
+
dimension: mass
|
|
73
|
+
factor: 0.001
|
|
74
|
+
spellings: gram, grams
|
|
75
|
+
uncefact: GRM
|
|
76
|
+
measure: oz
|
|
77
|
+
dimension: mass
|
|
78
|
+
factor: 0.028349523125
|
|
79
|
+
spellings: ounce, ounces
|
|
80
|
+
uncefact: ONZ
|
|
81
|
+
measure: lb
|
|
82
|
+
dimension: mass
|
|
83
|
+
factor: 0.45359237
|
|
84
|
+
spellings: lbs, pound, pounds
|
|
85
|
+
uncefact: LBR
|
|
86
|
+
|
|
87
|
+
measure: L
|
|
88
|
+
dimension: volume
|
|
89
|
+
factor: 1
|
|
90
|
+
rounding: 3
|
|
91
|
+
spellings: l, liter, liters, litre, litres
|
|
92
|
+
uncefact: LTR
|
|
93
|
+
measure: mL
|
|
94
|
+
dimension: volume
|
|
95
|
+
factor: 0.001
|
|
96
|
+
spellings: ml, milliliter, milliliters, millilitre, millilitres
|
|
97
|
+
uncefact: MLT
|
|
98
|
+
measure: floz
|
|
99
|
+
dimension: volume
|
|
100
|
+
factor: 0.0295735295625
|
|
101
|
+
spellings: fl oz, fl. oz., fluid ounce, fluid ounces
|
|
102
|
+
uncefact: OZA
|
|
103
|
+
measure: gal
|
|
104
|
+
dimension: volume
|
|
105
|
+
factor: 3.785411784
|
|
106
|
+
spellings: gallon, gallons
|
|
107
|
+
uncefact: GLL
|
|
108
|
+
|
|
109
|
+
measure: m2
|
|
110
|
+
dimension: area
|
|
111
|
+
factor: 1
|
|
112
|
+
rounding: 4
|
|
113
|
+
spellings: m², sqm, square meter, square meters
|
|
114
|
+
uncefact: MTK
|
|
115
|
+
measure: ft2
|
|
116
|
+
dimension: area
|
|
117
|
+
factor: 0.09290304
|
|
118
|
+
spellings: ft², sqft, square foot, square feet
|
|
119
|
+
uncefact: FTK
|
|
120
|
+
|
|
121
|
+
measure: K
|
|
122
|
+
dimension: temperature
|
|
123
|
+
factor: 1
|
|
124
|
+
rounding: 2
|
|
125
|
+
spellings: kelvin
|
|
126
|
+
uncefact: KEL
|
|
127
|
+
measure: °C
|
|
128
|
+
dimension: temperature
|
|
129
|
+
factor: 1
|
|
130
|
+
offset: 273.15
|
|
131
|
+
spellings: C, degC, celsius
|
|
132
|
+
uncefact: CEL
|
|
133
|
+
measure: °F
|
|
134
|
+
dimension: temperature
|
|
135
|
+
factor: 0.5555555555555556
|
|
136
|
+
offset: 255.37222222222223
|
|
137
|
+
spellings: F, degF, fahrenheit
|
|
138
|
+
uncefact: FAH
|
|
139
|
+
|
|
140
|
+
measure: B
|
|
141
|
+
dimension: data
|
|
142
|
+
factor: 1
|
|
143
|
+
rounding: 0
|
|
144
|
+
spellings: byte, bytes
|
|
145
|
+
uncefact: AD
|
|
146
|
+
measure: KB
|
|
147
|
+
dimension: data
|
|
148
|
+
factor: 1000
|
|
149
|
+
uncefact: 2P
|
|
150
|
+
measure: MB
|
|
151
|
+
dimension: data
|
|
152
|
+
factor: 1000000
|
|
153
|
+
uncefact: 4L
|
|
154
|
+
measure: GB
|
|
155
|
+
dimension: data
|
|
156
|
+
factor: 1000000000
|
|
157
|
+
uncefact: E34
|
|
158
|
+
measure: TB
|
|
159
|
+
dimension: data
|
|
160
|
+
factor: 1000000000000
|
|
161
|
+
uncefact: E35
|
|
162
|
+
|
|
163
|
+
measure: each
|
|
164
|
+
dimension: count
|
|
165
|
+
factor: 1
|
|
166
|
+
rounding: 0
|
|
167
|
+
spellings: ea, pc, pcs, piece, pieces
|
|
168
|
+
uncefact: EA
|
|
169
|
+
measure: dozen
|
|
170
|
+
dimension: count
|
|
171
|
+
factor: 12
|
|
172
|
+
spellings: dz, doz
|
|
173
|
+
uncefact: DZN
|
|
174
|
+
|
|
175
|
+
currency: USD
|
|
176
|
+
name: US dollar
|
|
177
|
+
places: 2
|
|
178
|
+
currency: EUR
|
|
179
|
+
name: Euro
|
|
180
|
+
places: 2
|
|
181
|
+
currency: GBP
|
|
182
|
+
name: Pound sterling
|
|
183
|
+
places: 2
|
|
184
|
+
currency: CAD
|
|
185
|
+
name: Canadian dollar
|
|
186
|
+
places: 2
|
|
187
|
+
currency: AUD
|
|
188
|
+
name: Australian dollar
|
|
189
|
+
places: 2
|
|
190
|
+
currency: MXN
|
|
191
|
+
name: Mexican peso
|
|
192
|
+
places: 2
|
|
193
|
+
currency: JPY
|
|
194
|
+
name: Yen
|
|
195
|
+
places: 0
|
|
196
|
+
currency: BHD
|
|
197
|
+
name: Bahraini dinar
|
|
198
|
+
places: 3
|
|
199
|
+
`;
|
|
200
|
+
//# sourceMappingURL=units-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"units-table.js","sourceRoot":"","sources":["../../src/units-table.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,4FAA4F;AAE5F,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoM7B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type Unit = {
|
|
2
|
+
unit: string;
|
|
3
|
+
dimension: string;
|
|
4
|
+
factor: number;
|
|
5
|
+
offset: number;
|
|
6
|
+
rounding?: number;
|
|
7
|
+
spellings: string[];
|
|
8
|
+
uncefact?: string;
|
|
9
|
+
extension?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type Currency = {
|
|
12
|
+
code: string;
|
|
13
|
+
name: string;
|
|
14
|
+
places: number;
|
|
15
|
+
};
|
|
16
|
+
export type UnitsTable = {
|
|
17
|
+
units: Map<string, Unit>;
|
|
18
|
+
currencies: Map<string, Currency>;
|
|
19
|
+
version: string;
|
|
20
|
+
};
|
|
21
|
+
/** Read a units table's records (measure and currency) from the text form. */
|
|
22
|
+
export declare function readUnits(text: string, into?: UnitsTable, extension?: boolean): UnitsTable;
|
|
23
|
+
/** The table in force: the standard table at its version, plus any extension. */
|
|
24
|
+
export declare function unitsTable(): UnitsTable;
|
|
25
|
+
/** Add an owner's units extension (11.9): its own units under its prefix, and spellings for standard ones. */
|
|
26
|
+
export declare function extendUnits(text: string): UnitsTable;
|
|
27
|
+
/** Back to the standard table alone. */
|
|
28
|
+
export declare function resetUnits(): void;
|
|
29
|
+
/** The real unit a spelling names, or null: the unit itself, or one of its spellings, folded. */
|
|
30
|
+
export declare function unitOf(spelling: string, table?: UnitsTable): string | null;
|
|
31
|
+
/** Is this a unit the table knows, `currency`, or an ISO 4217 code (1.4.4)? */
|
|
32
|
+
export declare function knownUnit(u: string, table?: UnitsTable): boolean;
|
|
33
|
+
export declare function dimensionOf(unit: string, table?: UnitsTable): string | null;
|
|
34
|
+
/** A currency's minor-unit places (ISO 4217), for a border that asks for them; 2 when unknown. */
|
|
35
|
+
export declare function currencyPlaces(code: string, table?: UnitsTable): number;
|
|
36
|
+
/**
|
|
37
|
+
* Convert an amount between units of one dimension: through the base by factor and offset, rounded to
|
|
38
|
+
* `places`, else the dimension's rounding, else 6 places with trailing zeros dropped.
|
|
39
|
+
*/
|
|
40
|
+
export declare function convert(amount: string, from: string, to: string, places?: number, table?: UnitsTable): string | null;
|
|
41
|
+
/** The standard table plus one owner's extension, as a table of its own (11.9): per dictionary, never global. */
|
|
42
|
+
export declare function unitsTableWith(extension?: string): UnitsTable;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// units.ts: the units table (spec 1.4.3, 11.9), read from the standard package's reference records
|
|
2
|
+
// (crubal.com/units, embedded as units-table.ts and checked against std/units/units.crubal) plus an owner's
|
|
3
|
+
// extension. Spellings fold to a unit; amounts convert within a dimension by factor and offset, rounded to
|
|
4
|
+
// the facet's places or the dimension's rounding. A spelling nobody knows is a unit question for review,
|
|
5
|
+
// never a unit minted on sight.
|
|
6
|
+
import { readTree } from "./tree.js";
|
|
7
|
+
import { STANDARD_UNITS } from "./units-table.js";
|
|
8
|
+
const foldSpelling = (s) => s.normalize("NFC").toLowerCase().replace(/\s+/g, " ").trim();
|
|
9
|
+
/** Read a units table's records (measure and currency) from the text form. */
|
|
10
|
+
export function readUnits(text, into, extension = false) {
|
|
11
|
+
const table = into ?? { units: new Map(), currencies: new Map(), version: "" };
|
|
12
|
+
for (const n of readTree(text)) {
|
|
13
|
+
if (n.kind !== "pair" || !n.key)
|
|
14
|
+
continue;
|
|
15
|
+
const get = (k) => n.children.find((c) => c.key === k)?.value.trim();
|
|
16
|
+
if (n.key === "package")
|
|
17
|
+
table.version = n.value.split(" /")[1]?.trim() ?? table.version;
|
|
18
|
+
if (n.key === "measure") {
|
|
19
|
+
const name = n.value.trim();
|
|
20
|
+
const have = table.units.get(name);
|
|
21
|
+
const spellings = (get("spellings") ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
22
|
+
// An extension may add spellings to a standard unit; it never changes its factor or dimension (11.9).
|
|
23
|
+
if (have && extension) {
|
|
24
|
+
have.spellings = [...have.spellings, ...spellings.filter((s) => !have.spellings.includes(s))];
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const u = { unit: name, dimension: get("dimension") ?? "", factor: Number(get("factor") ?? 1), offset: Number(get("offset") ?? 0), spellings, ...(extension ? { extension: true } : {}) };
|
|
28
|
+
const r = get("rounding");
|
|
29
|
+
if (r !== undefined)
|
|
30
|
+
u.rounding = Number(r);
|
|
31
|
+
const code = get("uncefact");
|
|
32
|
+
if (code)
|
|
33
|
+
u.uncefact = code;
|
|
34
|
+
table.units.set(name, u);
|
|
35
|
+
}
|
|
36
|
+
if (n.key === "currency")
|
|
37
|
+
table.currencies.set(n.value.trim(), { code: n.value.trim(), name: get("name") ?? "", places: Number(get("places") ?? 2) });
|
|
38
|
+
}
|
|
39
|
+
return table;
|
|
40
|
+
}
|
|
41
|
+
let current = readUnits(STANDARD_UNITS);
|
|
42
|
+
/** The table in force: the standard table at its version, plus any extension. */
|
|
43
|
+
export function unitsTable() {
|
|
44
|
+
return current;
|
|
45
|
+
}
|
|
46
|
+
/** Add an owner's units extension (11.9): its own units under its prefix, and spellings for standard ones. */
|
|
47
|
+
export function extendUnits(text) {
|
|
48
|
+
current = readUnits(text, current, true);
|
|
49
|
+
return current;
|
|
50
|
+
}
|
|
51
|
+
/** Back to the standard table alone. */
|
|
52
|
+
export function resetUnits() {
|
|
53
|
+
current = readUnits(STANDARD_UNITS);
|
|
54
|
+
}
|
|
55
|
+
/** The real unit a spelling names, or null: the unit itself, or one of its spellings, folded. */
|
|
56
|
+
export function unitOf(spelling, table = current) {
|
|
57
|
+
if (table.units.has(spelling))
|
|
58
|
+
return spelling;
|
|
59
|
+
const k = foldSpelling(spelling);
|
|
60
|
+
for (const u of table.units.values())
|
|
61
|
+
if (u.unit.toLowerCase() === k || u.spellings.some((s) => foldSpelling(s) === k))
|
|
62
|
+
return u.unit;
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
/** Is this a unit the table knows, `currency`, or an ISO 4217 code (1.4.4)? */
|
|
66
|
+
export function knownUnit(u, table = current) {
|
|
67
|
+
return u === "currency" || /^[A-Z]{3}$/.test(u) || table.units.has(u);
|
|
68
|
+
}
|
|
69
|
+
export function dimensionOf(unit, table = current) {
|
|
70
|
+
return table.units.get(unit)?.dimension ?? null;
|
|
71
|
+
}
|
|
72
|
+
/** A currency's minor-unit places (ISO 4217), for a border that asks for them; 2 when unknown. */
|
|
73
|
+
export function currencyPlaces(code, table = current) {
|
|
74
|
+
return table.currencies.get(code)?.places ?? 2;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Convert an amount between units of one dimension: through the base by factor and offset, rounded to
|
|
78
|
+
* `places`, else the dimension's rounding, else 6 places with trailing zeros dropped.
|
|
79
|
+
*/
|
|
80
|
+
export function convert(amount, from, to, places, table = current) {
|
|
81
|
+
const a = table.units.get(from);
|
|
82
|
+
const b = table.units.get(to);
|
|
83
|
+
if (!a || !b || a.dimension !== b.dimension)
|
|
84
|
+
return null;
|
|
85
|
+
const base = Number(amount) * a.factor + a.offset;
|
|
86
|
+
const v = (base - b.offset) / b.factor;
|
|
87
|
+
// The facet's places are kept exactly; the dimension's rounding is a most, trailing zeros dropped.
|
|
88
|
+
if (places !== undefined)
|
|
89
|
+
return v.toFixed(places);
|
|
90
|
+
const dimRounding = [...table.units.values()].find((u) => u.dimension === a.dimension && u.factor === 1 && u.offset === 0)?.rounding;
|
|
91
|
+
return String(Number(v.toFixed(dimRounding ?? 6)));
|
|
92
|
+
}
|
|
93
|
+
/** The standard table plus one owner's extension, as a table of its own (11.9): per dictionary, never global. */
|
|
94
|
+
export function unitsTableWith(extension) {
|
|
95
|
+
const table = readUnits(STANDARD_UNITS);
|
|
96
|
+
return extension ? readUnits(extension, table, true) : table;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=units.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/units.ts"],"names":[],"mappings":"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"}
|