@robosystems/report-components 0.4.0 → 0.5.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/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A source-agnostic React library for rendering XBRL-grade financial statements. T
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
10
|
- **Components** — `ReportView`, `StatementTable`, `FactInspector`, and `ExternalTextBlock` for full statements down to per-fact inspection
|
|
11
|
-
- **
|
|
11
|
+
- **Five reference adapters** (under `/adapters`) — `parseJsonld` for canonical `holon.jsonld` files, `parseTavi` for `tavi.json` (the same filing as a Project Tavi compiled model, XBRL International's draft — the same facts, walked directly with no RDF step; `parseReportDocument` sniffs which of the two it was handed), `cypherAdapter` for live graphs over GraphQL, `fetchSecReportShell`/`fetchSecSection` for the SEC repository, and `parseStore` for pre-parsed RDF stores
|
|
12
12
|
- **Correct-by-construction rendering** — presentation-order walk, calculation-subtotal footing, multi-factSet facts, and structure-title/kind parsing shared across all sources
|
|
13
13
|
- **Plain React, ESM, tree-shakeable** — `react`/`react-dom` peers only, no framework-specific imports; the same package feeds a Next.js app or a lightweight Vite app
|
|
14
14
|
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,2 +1,105 @@
|
|
|
1
|
-
|
|
1
|
+
import { N as NormalizedReport, R as ReportAdapter } from '../store-DlU7XE-S.js';
|
|
2
|
+
export { C as CypherAdapterConfig, S as SecQuery, a as SecReportShell, b as SecSection, c as SectionKind, d as cypherAdapter, f as fetchSecReportShell, e as fetchSecSection, j as jsonldFileAdapter, m as mergeSecSections, p as parseJsonld, g as parseStore, h as parseStructureDefinition, i as parseStructureName } from '../store-DlU7XE-S.js';
|
|
2
3
|
import 'n3';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One door for both of xbrlkit's JSON projections. A holon is dataset-form
|
|
7
|
+
* JSON-LD (a `@context` and named graphs); a Tavi model announces itself in
|
|
8
|
+
* `documentInfo.documentType`. Callers that take "a report file" — a dropped
|
|
9
|
+
* file, a URL — sniff here and never need to know which they were handed.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
type ReportFormat = 'holon' | 'tavi';
|
|
13
|
+
/** The format of a parsed report document, or null when it is neither. */
|
|
14
|
+
declare function detectReportFormat(doc: unknown): ReportFormat | null;
|
|
15
|
+
/** Parse a report document (string or object) whichever JSON projection it is. */
|
|
16
|
+
declare function parseReportDocument(doc: string | object): Promise<{
|
|
17
|
+
format: ReportFormat;
|
|
18
|
+
report: NormalizedReport;
|
|
19
|
+
}>;
|
|
20
|
+
|
|
21
|
+
interface TaviProperty {
|
|
22
|
+
property: string;
|
|
23
|
+
value?: unknown;
|
|
24
|
+
}
|
|
25
|
+
interface TaviNamed {
|
|
26
|
+
name: string;
|
|
27
|
+
}
|
|
28
|
+
interface TaviConcept extends TaviNamed {
|
|
29
|
+
dataType?: string | null;
|
|
30
|
+
periodType?: string | null;
|
|
31
|
+
properties?: TaviProperty[];
|
|
32
|
+
}
|
|
33
|
+
interface TaviDimension extends TaviNamed {
|
|
34
|
+
domainClass?: string | null;
|
|
35
|
+
}
|
|
36
|
+
interface TaviUnit extends TaviNamed {
|
|
37
|
+
dataType?: string;
|
|
38
|
+
compositeUnitRepresentation?: string[];
|
|
39
|
+
}
|
|
40
|
+
interface TaviLabel {
|
|
41
|
+
forObject: string;
|
|
42
|
+
labelType: string;
|
|
43
|
+
value: string;
|
|
44
|
+
language?: string;
|
|
45
|
+
}
|
|
46
|
+
interface TaviRelationship {
|
|
47
|
+
source: string;
|
|
48
|
+
target: string;
|
|
49
|
+
order?: number;
|
|
50
|
+
properties?: TaviProperty[];
|
|
51
|
+
}
|
|
52
|
+
interface TaviNetwork extends TaviNamed {
|
|
53
|
+
relationshipTypeName?: string;
|
|
54
|
+
relationships?: TaviRelationship[];
|
|
55
|
+
roots?: string[];
|
|
56
|
+
}
|
|
57
|
+
interface TaviGroup extends TaviNamed {
|
|
58
|
+
groupURI?: string;
|
|
59
|
+
}
|
|
60
|
+
interface TaviGroupContent {
|
|
61
|
+
groupName: string;
|
|
62
|
+
forObject: string;
|
|
63
|
+
}
|
|
64
|
+
interface TaviFactValue {
|
|
65
|
+
value?: unknown;
|
|
66
|
+
decimals?: unknown;
|
|
67
|
+
}
|
|
68
|
+
interface TaviFact extends TaviNamed {
|
|
69
|
+
factDimensions?: Record<string, unknown>;
|
|
70
|
+
factValues?: TaviFactValue[];
|
|
71
|
+
}
|
|
72
|
+
interface TaviModel {
|
|
73
|
+
name?: string;
|
|
74
|
+
modelType?: string;
|
|
75
|
+
properties?: TaviProperty[];
|
|
76
|
+
entities?: TaviNamed[];
|
|
77
|
+
units?: TaviUnit[];
|
|
78
|
+
concepts?: TaviConcept[];
|
|
79
|
+
headings?: TaviNamed[];
|
|
80
|
+
dimensions?: TaviDimension[];
|
|
81
|
+
domainClasses?: TaviNamed[];
|
|
82
|
+
members?: TaviNamed[];
|
|
83
|
+
labels?: TaviLabel[];
|
|
84
|
+
networks?: TaviNetwork[];
|
|
85
|
+
groups?: TaviGroup[];
|
|
86
|
+
groupContents?: TaviGroupContent[];
|
|
87
|
+
facts?: TaviFact[];
|
|
88
|
+
}
|
|
89
|
+
/** A Tavi document: the envelope and the model. */
|
|
90
|
+
interface TaviDocument {
|
|
91
|
+
documentInfo?: {
|
|
92
|
+
documentType?: string;
|
|
93
|
+
namespaces?: Record<string, string>;
|
|
94
|
+
description?: string;
|
|
95
|
+
};
|
|
96
|
+
xbrlModel?: TaviModel;
|
|
97
|
+
}
|
|
98
|
+
/** Whether a parsed document is a Tavi model (a `documentInfo.documentType` under xbrl.org, or an `xbrlModel` report). */
|
|
99
|
+
declare function isTaviDocument(doc: unknown): doc is TaviDocument;
|
|
100
|
+
/** Parse a `tavi.json` document (string or parsed object) into the model. */
|
|
101
|
+
declare function parseTavi(doc: string | object): NormalizedReport;
|
|
102
|
+
/** A `ReportAdapter` over an in-memory `tavi.json` document. */
|
|
103
|
+
declare function taviFileAdapter(doc: string | object, source?: string): ReportAdapter;
|
|
104
|
+
|
|
105
|
+
export { ReportAdapter, type ReportFormat, type TaviDocument, detectReportFormat, isTaviDocument, parseReportDocument, parseTavi, taviFileAdapter };
|
package/dist/adapters/index.js
CHANGED
|
@@ -1,3 +1,364 @@
|
|
|
1
|
+
import { stripRoleSuffix, humanize, parseJsonld, parseStructureName } from '../chunk-GRR34QLV.js';
|
|
1
2
|
export { cypherAdapter, fetchSecReportShell, fetchSecSection, jsonldFileAdapter, mergeSecSections, parseJsonld, parseStore, parseStructureDefinition, parseStructureName } from '../chunk-GRR34QLV.js';
|
|
3
|
+
|
|
4
|
+
// src/adapters/tavi.ts
|
|
5
|
+
var TAVI_DOCUMENT_TYPE = /xbrl\.org\/(PWD|20\d\d)\//;
|
|
6
|
+
var PRESENTATION = "xbrl:parent-child";
|
|
7
|
+
var CALCULATION = "xbrl:summation-item";
|
|
8
|
+
var ROOT_SOURCE = "xbrl:rootSource";
|
|
9
|
+
var CORE_ASPECTS = /* @__PURE__ */ new Set([
|
|
10
|
+
"xbrl:concept",
|
|
11
|
+
"xbrl:period",
|
|
12
|
+
"xbrl:entity",
|
|
13
|
+
"xbrl:unit",
|
|
14
|
+
"xbrl:language"
|
|
15
|
+
]);
|
|
16
|
+
var STANDARD_LABEL = "xbrl:label";
|
|
17
|
+
var REGISTRANT_NAME = "dei:EntityRegistrantName";
|
|
18
|
+
function isTaviDocument(doc) {
|
|
19
|
+
if (!doc || typeof doc !== "object") return false;
|
|
20
|
+
const d = doc;
|
|
21
|
+
if (!d.xbrlModel || typeof d.xbrlModel !== "object") return false;
|
|
22
|
+
const type = d.documentInfo?.documentType;
|
|
23
|
+
return typeof type === "string" && TAVI_DOCUMENT_TYPE.test(type) || d.xbrlModel.modelType === "xbrl:report";
|
|
24
|
+
}
|
|
25
|
+
function propertyValue(props, name) {
|
|
26
|
+
return props?.find((p) => p.property === name)?.value;
|
|
27
|
+
}
|
|
28
|
+
function toNumber(raw) {
|
|
29
|
+
if (typeof raw === "number") return Number.isFinite(raw) ? raw : null;
|
|
30
|
+
if (typeof raw === "string" && raw.trim() !== "") {
|
|
31
|
+
const n = Number(raw);
|
|
32
|
+
return Number.isNaN(n) ? null : n;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function localName(qname) {
|
|
37
|
+
const i = qname.indexOf(":");
|
|
38
|
+
return i >= 0 ? qname.slice(i + 1) : qname;
|
|
39
|
+
}
|
|
40
|
+
function itemTypeOf(dataType) {
|
|
41
|
+
if (!dataType) return {};
|
|
42
|
+
const local = localName(dataType);
|
|
43
|
+
switch (local) {
|
|
44
|
+
case "monetary":
|
|
45
|
+
return { itemType: "monetary", numericKind: "monetary" };
|
|
46
|
+
case "perShare":
|
|
47
|
+
return { itemType: "perShare", numericKind: "perShare" };
|
|
48
|
+
case "percent":
|
|
49
|
+
return { itemType: "percent", numericKind: "percent" };
|
|
50
|
+
case "pure":
|
|
51
|
+
return { itemType: "pure", numericKind: "pure" };
|
|
52
|
+
case "sharesType":
|
|
53
|
+
case "shares":
|
|
54
|
+
return { itemType: "shares", numericKind: "shares" };
|
|
55
|
+
case "integer":
|
|
56
|
+
case "int":
|
|
57
|
+
case "long":
|
|
58
|
+
case "nonNegativeInteger":
|
|
59
|
+
return { itemType: "integer", numericKind: "integer" };
|
|
60
|
+
case "decimal":
|
|
61
|
+
case "float":
|
|
62
|
+
case "double":
|
|
63
|
+
return { itemType: "decimal" };
|
|
64
|
+
case "textBlock":
|
|
65
|
+
return { itemType: "textBlock" };
|
|
66
|
+
case "boolean":
|
|
67
|
+
return { itemType: "boolean" };
|
|
68
|
+
case "date":
|
|
69
|
+
case "dateTime":
|
|
70
|
+
return { itemType: "date" };
|
|
71
|
+
case "string":
|
|
72
|
+
case "normalizedString":
|
|
73
|
+
case "token":
|
|
74
|
+
return { itemType: "string" };
|
|
75
|
+
default:
|
|
76
|
+
return { itemType: local };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function periodOf(literal) {
|
|
80
|
+
const [first, second] = literal.split("/");
|
|
81
|
+
if (second === void 0) {
|
|
82
|
+
const instant = inclusiveDate(first);
|
|
83
|
+
return { id: literal, type: "instant", instant, startDate: null, endDate: null, end: instant };
|
|
84
|
+
}
|
|
85
|
+
const startDate = datePart(first);
|
|
86
|
+
const endDate = inclusiveDate(second);
|
|
87
|
+
return { id: literal, type: "duration", instant: null, startDate, endDate, end: endDate };
|
|
88
|
+
}
|
|
89
|
+
function datePart(value) {
|
|
90
|
+
return value.slice(0, 10);
|
|
91
|
+
}
|
|
92
|
+
function inclusiveDate(value) {
|
|
93
|
+
const date = datePart(value);
|
|
94
|
+
if (!/T/.test(value)) return date;
|
|
95
|
+
const t = Date.parse(`${date}T00:00:00Z`);
|
|
96
|
+
if (Number.isNaN(t)) return date;
|
|
97
|
+
return new Date(t - 864e5).toISOString().slice(0, 10);
|
|
98
|
+
}
|
|
99
|
+
function parseTavi(doc) {
|
|
100
|
+
const json = typeof doc === "string" ? JSON.parse(doc) : doc;
|
|
101
|
+
const model = json.xbrlModel ?? {};
|
|
102
|
+
const namespaces = json.documentInfo?.namespaces ?? {};
|
|
103
|
+
const labels = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const l of model.labels ?? []) {
|
|
105
|
+
if (!l.forObject || !l.labelType || typeof l.value !== "string") continue;
|
|
106
|
+
let byType = labels.get(l.forObject);
|
|
107
|
+
if (!byType) {
|
|
108
|
+
byType = /* @__PURE__ */ new Map();
|
|
109
|
+
labels.set(l.forObject, byType);
|
|
110
|
+
}
|
|
111
|
+
if (!byType.has(l.labelType)) byType.set(l.labelType, l.value);
|
|
112
|
+
}
|
|
113
|
+
const labelOf = (name, type = STANDARD_LABEL) => labels.get(name)?.get(type) ?? null;
|
|
114
|
+
const displayLabel = (name) => {
|
|
115
|
+
const standard = labelOf(name);
|
|
116
|
+
return standard ? stripRoleSuffix(standard) : humanize(name);
|
|
117
|
+
};
|
|
118
|
+
const facts = model.facts ?? [];
|
|
119
|
+
const sharesConcepts = /* @__PURE__ */ new Set();
|
|
120
|
+
for (const f of facts) {
|
|
121
|
+
const dims = f.factDimensions ?? {};
|
|
122
|
+
const unit = dims["xbrl:unit"];
|
|
123
|
+
const concept = dims["xbrl:concept"];
|
|
124
|
+
if (typeof unit === "string" && typeof concept === "string" && localName(unit) === "shares") {
|
|
125
|
+
sharesConcepts.add(concept);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const elements = {};
|
|
129
|
+
for (const c of model.concepts ?? []) {
|
|
130
|
+
const balanceValue = propertyValue(c.properties, "xbrla:balance");
|
|
131
|
+
const balance = balanceValue === "debit" || balanceValue === "credit" ? balanceValue : null;
|
|
132
|
+
const periodType = c.periodType === "instant" || c.periodType === "duration" ? c.periodType : null;
|
|
133
|
+
const typed = itemTypeOf(c.dataType);
|
|
134
|
+
const asShares = !typed.numericKind && sharesConcepts.has(c.name);
|
|
135
|
+
elements[c.name] = {
|
|
136
|
+
id: c.name,
|
|
137
|
+
qname: c.name,
|
|
138
|
+
label: displayLabel(c.name),
|
|
139
|
+
balance,
|
|
140
|
+
periodType,
|
|
141
|
+
abstract: false,
|
|
142
|
+
monetary: typed.numericKind === "monetary",
|
|
143
|
+
itemType: asShares ? "shares" : typed.itemType,
|
|
144
|
+
numericKind: asShares ? "shares" : typed.numericKind
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const structural = [
|
|
148
|
+
...model.headings ?? [],
|
|
149
|
+
...model.dimensions ?? [],
|
|
150
|
+
...model.domainClasses ?? [],
|
|
151
|
+
...model.members ?? []
|
|
152
|
+
];
|
|
153
|
+
for (const s of structural) {
|
|
154
|
+
if (!s.name || elements[s.name]) continue;
|
|
155
|
+
elements[s.name] = {
|
|
156
|
+
id: s.name,
|
|
157
|
+
qname: s.name,
|
|
158
|
+
label: displayLabel(s.name),
|
|
159
|
+
balance: null,
|
|
160
|
+
periodType: null,
|
|
161
|
+
abstract: true,
|
|
162
|
+
monetary: false
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const explicitAxes = new Set(
|
|
166
|
+
(model.dimensions ?? []).filter((d) => d.domainClass).map((d) => d.name)
|
|
167
|
+
);
|
|
168
|
+
const units = {};
|
|
169
|
+
for (const u of model.units ?? []) {
|
|
170
|
+
if (!u.name) continue;
|
|
171
|
+
const measure = u.compositeUnitRepresentation?.[0] ?? u.name;
|
|
172
|
+
units[u.name] = {
|
|
173
|
+
id: u.name,
|
|
174
|
+
measure,
|
|
175
|
+
label: measure.includes("/") ? measure.split("/").map(localName).join("/") : localName(measure)
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const groups = /* @__PURE__ */ new Map();
|
|
179
|
+
for (const g of model.groups ?? []) groups.set(g.name, g);
|
|
180
|
+
const groupOf = /* @__PURE__ */ new Map();
|
|
181
|
+
for (const gc of model.groupContents ?? []) groupOf.set(gc.forObject, gc.groupName);
|
|
182
|
+
const groupIndex = /* @__PURE__ */ new Map();
|
|
183
|
+
(model.groups ?? []).forEach((g, i) => groupIndex.set(g.name, i));
|
|
184
|
+
const networks = model.networks ?? [];
|
|
185
|
+
const structures = [];
|
|
186
|
+
const informationBlocks = [];
|
|
187
|
+
const presAssociations = [];
|
|
188
|
+
const calcAssociations = [];
|
|
189
|
+
const presentedIn = /* @__PURE__ */ new Map();
|
|
190
|
+
const presentationOfGroup = /* @__PURE__ */ new Map();
|
|
191
|
+
const sectionMeta = (groupName) => {
|
|
192
|
+
const group = groupName ? groups.get(groupName) : void 0;
|
|
193
|
+
const definition = groupName ? labelOf(groupName) : null;
|
|
194
|
+
const parsed = parseStructureName(definition);
|
|
195
|
+
const roleUri = group?.groupURI ?? null;
|
|
196
|
+
const fallback = roleUri ? humanize(roleUri) : groupName ? humanize(groupName) : "Section";
|
|
197
|
+
const sortCode = definition ? /^\s*(\d+)\s*-/.exec(definition)?.[1] : void 0;
|
|
198
|
+
return {
|
|
199
|
+
roleUri,
|
|
200
|
+
definition: parsed.definition,
|
|
201
|
+
title: parsed.title ?? fallback,
|
|
202
|
+
kind: parsed.kind,
|
|
203
|
+
order: sortCode ? Number(sortCode) : groupName ? groupIndex.get(groupName) ?? void 0 : void 0
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
for (const n of networks) {
|
|
207
|
+
if (n.relationshipTypeName !== PRESENTATION) continue;
|
|
208
|
+
const groupName = groupOf.get(n.name);
|
|
209
|
+
const meta = sectionMeta(groupName);
|
|
210
|
+
if (groupName && !presentationOfGroup.has(groupName)) presentationOfGroup.set(groupName, n.name);
|
|
211
|
+
structures.push({
|
|
212
|
+
id: n.name,
|
|
213
|
+
blockType: "",
|
|
214
|
+
roleUri: meta.roleUri,
|
|
215
|
+
structureName: meta.title,
|
|
216
|
+
definition: meta.definition,
|
|
217
|
+
kind: meta.kind,
|
|
218
|
+
order: meta.order
|
|
219
|
+
});
|
|
220
|
+
informationBlocks.push({
|
|
221
|
+
id: n.name,
|
|
222
|
+
blockType: "",
|
|
223
|
+
factSet: n.name,
|
|
224
|
+
label: meta.title,
|
|
225
|
+
structureId: n.name
|
|
226
|
+
});
|
|
227
|
+
for (const r of n.relationships ?? []) {
|
|
228
|
+
if (!r.source || !r.target) continue;
|
|
229
|
+
for (const node of r.source === ROOT_SOURCE ? [r.target] : [r.source, r.target]) {
|
|
230
|
+
const list = presentedIn.get(node);
|
|
231
|
+
if (!list) presentedIn.set(node, [n.name]);
|
|
232
|
+
else if (!list.includes(n.name)) list.push(n.name);
|
|
233
|
+
}
|
|
234
|
+
if (r.source === ROOT_SOURCE) continue;
|
|
235
|
+
const preferred = propertyValue(r.properties, "xbrl:preferredLabel");
|
|
236
|
+
const preferredType = typeof preferred === "string" ? preferred : null;
|
|
237
|
+
const preferredText = preferredType && preferredType !== STANDARD_LABEL ? labelOf(r.target, preferredType) : null;
|
|
238
|
+
presAssociations.push({
|
|
239
|
+
parent: r.source,
|
|
240
|
+
child: r.target,
|
|
241
|
+
order: toNumber(r.order) ?? 0,
|
|
242
|
+
role: meta.roleUri,
|
|
243
|
+
structure: n.name,
|
|
244
|
+
preferredLabel: preferredText ? stripRoleSuffix(preferredText) : null,
|
|
245
|
+
preferredLabelRole: preferredType
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
for (const n of networks) {
|
|
250
|
+
if (n.relationshipTypeName !== CALCULATION) continue;
|
|
251
|
+
const groupName = groupOf.get(n.name);
|
|
252
|
+
const structure = (groupName && presentationOfGroup.get(groupName)) ?? null;
|
|
253
|
+
const roleUri = groupName ? groups.get(groupName)?.groupURI ?? null : null;
|
|
254
|
+
for (const r of n.relationships ?? []) {
|
|
255
|
+
if (!r.source || !r.target || r.source === ROOT_SOURCE) continue;
|
|
256
|
+
calcAssociations.push({
|
|
257
|
+
parent: r.source,
|
|
258
|
+
child: r.target,
|
|
259
|
+
weight: toNumber(propertyValue(r.properties, "xbrl:weight")) ?? 1,
|
|
260
|
+
order: toNumber(r.order) ?? 0,
|
|
261
|
+
role: roleUri,
|
|
262
|
+
structure
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const periods = {};
|
|
267
|
+
const out = [];
|
|
268
|
+
let registrantName = null;
|
|
269
|
+
for (const f of facts) {
|
|
270
|
+
const dims = f.factDimensions ?? {};
|
|
271
|
+
const element = dims["xbrl:concept"];
|
|
272
|
+
const periodLiteral = dims["xbrl:period"];
|
|
273
|
+
if (typeof element !== "string" || typeof periodLiteral !== "string") continue;
|
|
274
|
+
if (!periods[periodLiteral]) periods[periodLiteral] = periodOf(periodLiteral);
|
|
275
|
+
const unit = typeof dims["xbrl:unit"] === "string" ? dims["xbrl:unit"] : null;
|
|
276
|
+
const entity2 = typeof dims["xbrl:entity"] === "string" ? dims["xbrl:entity"] : null;
|
|
277
|
+
const first = f.factValues?.[0];
|
|
278
|
+
const raw = first?.value;
|
|
279
|
+
const numeric = elements[element]?.numericKind !== void 0 || elements[element]?.itemType === "decimal";
|
|
280
|
+
const value = numeric || typeof raw === "number" ? toNumber(raw) : null;
|
|
281
|
+
const textValue = value === null && raw !== void 0 && raw !== null ? String(raw) : null;
|
|
282
|
+
if (element === REGISTRANT_NAME && textValue && !registrantName) registrantName = textValue;
|
|
283
|
+
const decimalsRaw = first?.decimals;
|
|
284
|
+
const decimals = typeof decimalsRaw === "number" ? String(decimalsRaw) : typeof decimalsRaw === "string" ? decimalsRaw : null;
|
|
285
|
+
const dimensions = [];
|
|
286
|
+
for (const [axis, member] of Object.entries(dims)) {
|
|
287
|
+
if (CORE_ASPECTS.has(axis)) continue;
|
|
288
|
+
const explicit = explicitAxes.has(axis) && typeof member === "string" && member.includes(":");
|
|
289
|
+
const memberName = explicit ? member : null;
|
|
290
|
+
const typedValue = explicit ? null : member === null || member === void 0 ? null : String(member);
|
|
291
|
+
dimensions.push({
|
|
292
|
+
axis,
|
|
293
|
+
member: memberName,
|
|
294
|
+
axisLabel: elements[axis]?.label ?? humanize(axis),
|
|
295
|
+
memberLabel: memberName ? elements[memberName]?.label ?? humanize(memberName) : typedValue ?? "",
|
|
296
|
+
explicit,
|
|
297
|
+
typedValue
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
const factSets = presentedIn.get(element) ?? [];
|
|
301
|
+
out.push({
|
|
302
|
+
id: f.name,
|
|
303
|
+
element,
|
|
304
|
+
period: periodLiteral,
|
|
305
|
+
unit,
|
|
306
|
+
entity: entity2,
|
|
307
|
+
factSet: factSets[0] ?? null,
|
|
308
|
+
factSets: factSets.length ? [...factSets] : void 0,
|
|
309
|
+
value,
|
|
310
|
+
textValue,
|
|
311
|
+
contentType: null,
|
|
312
|
+
decimals,
|
|
313
|
+
dimensions: dimensions.length ? dimensions : void 0
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
const entityName = model.entities?.[0]?.name ?? null;
|
|
317
|
+
const entity = entityName ? {
|
|
318
|
+
id: entityName,
|
|
319
|
+
name: registrantName ?? humanize(entityName),
|
|
320
|
+
legalName: registrantName,
|
|
321
|
+
country: null
|
|
322
|
+
} : null;
|
|
323
|
+
const reportIri = namespaces.rpt ?? null;
|
|
324
|
+
const reportId = reportIri ? reportIri.replace(/\/$/, "").split("/").pop() ?? null : model.name ?? null;
|
|
325
|
+
return {
|
|
326
|
+
reportId,
|
|
327
|
+
reportIri,
|
|
328
|
+
entity,
|
|
329
|
+
informationBlocks,
|
|
330
|
+
structures,
|
|
331
|
+
facts: out,
|
|
332
|
+
elements,
|
|
333
|
+
periods,
|
|
334
|
+
units,
|
|
335
|
+
calcAssociations,
|
|
336
|
+
presAssociations
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
function taviFileAdapter(doc, source = "tavi.json") {
|
|
340
|
+
return {
|
|
341
|
+
source,
|
|
342
|
+
load: async () => parseTavi(doc)
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// src/adapters/detect.ts
|
|
347
|
+
function detectReportFormat(doc) {
|
|
348
|
+
if (!doc || typeof doc !== "object") return null;
|
|
349
|
+
if (isTaviDocument(doc)) return "tavi";
|
|
350
|
+
const d = doc;
|
|
351
|
+
if ("@context" in d || "@graph" in d || "@id" in d) return "holon";
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
async function parseReportDocument(doc) {
|
|
355
|
+
const json = typeof doc === "string" ? JSON.parse(doc) : doc;
|
|
356
|
+
const format = detectReportFormat(json);
|
|
357
|
+
if (format === "tavi") return { format, report: parseTavi(json) };
|
|
358
|
+
if (format === "holon") return { format, report: await parseJsonld(json) };
|
|
359
|
+
throw new Error("Not a report document: expected a holon (JSON-LD) or a Tavi compiled model");
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export { detectReportFormat, isTaviDocument, parseReportDocument, parseTavi, taviFileAdapter };
|
|
2
363
|
//# sourceMappingURL=index.js.map
|
|
3
364
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/tavi.ts","../../src/adapters/detect.ts"],"names":["entity"],"mappings":";;;;AA4HA,IAAM,kBAAA,GAAqB,2BAAA;AAC3B,IAAM,YAAA,GAAe,mBAAA;AACrB,IAAM,WAAA,GAAc,qBAAA;AACpB,IAAM,WAAA,GAAc,iBAAA;AAEpB,IAAM,YAAA,uBAAmB,GAAA,CAAI;AAAA,EAC3B,cAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAC,CAAA;AACD,IAAM,cAAA,GAAiB,YAAA;AACvB,IAAM,eAAA,GAAkB,0BAAA;AAGjB,SAAS,eAAe,GAAA,EAAmC;AAChE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,KAAA;AAC5C,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,IAAI,CAAC,CAAA,CAAE,SAAA,IAAa,OAAO,CAAA,CAAE,SAAA,KAAc,UAAU,OAAO,KAAA;AAC5D,EAAA,MAAM,IAAA,GAAO,EAAE,YAAA,EAAc,YAAA;AAC7B,EAAA,OACG,OAAO,SAAS,QAAA,IAAY,kBAAA,CAAmB,KAAK,IAAI,CAAA,IACzD,CAAA,CAAE,SAAA,CAAU,SAAA,KAAc,aAAA;AAE9B;AAIA,SAAS,aAAA,CAAc,OAAmC,IAAA,EAAuB;AAC/E,EAAA,OAAO,OAAO,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,QAAA,KAAa,IAAI,CAAA,EAAG,KAAA;AAClD;AAEA,SAAS,SAAS,GAAA,EAA6B;AAC7C,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU,OAAO,OAAO,QAAA,CAAS,GAAG,IAAI,GAAA,GAAM,IAAA;AACjE,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,IAAA,OAAW,EAAA,EAAI;AAChD,IAAA,MAAM,CAAA,GAAI,OAAO,GAAG,CAAA;AACpB,IAAA,OAAO,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,GAAO,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,UAAU,KAAA,EAAuB;AACxC,EAAA,MAAM,CAAA,GAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC3B,EAAA,OAAO,KAAK,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,GAAI,KAAA;AACvC;AAQA,SAAS,WAAW,QAAA,EAGlB;AACA,EAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AACvB,EAAA,MAAM,KAAA,GAAQ,UAAU,QAAQ,CAAA;AAChC,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,WAAA,EAAa,UAAA,EAAW;AAAA,IACzD,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,WAAA,EAAa,UAAA,EAAW;AAAA,IACzD,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,WAAA,EAAa,SAAA,EAAU;AAAA,IACvD,KAAK,MAAA;AACH,MAAA,OAAO,EAAE,QAAA,EAAU,MAAA,EAAQ,WAAA,EAAa,MAAA,EAAO;AAAA,IACjD,KAAK,YAAA;AAAA,IACL,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,QAAA,EAAU,QAAA,EAAU,WAAA,EAAa,QAAA,EAAS;AAAA,IACrD,KAAK,SAAA;AAAA,IACL,KAAK,KAAA;AAAA,IACL,KAAK,MAAA;AAAA,IACL,KAAK,oBAAA;AACH,MAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,WAAA,EAAa,SAAA,EAAU;AAAA,IACvD,KAAK,SAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,UAAU,SAAA,EAAU;AAAA,IAC/B,KAAK,WAAA;AACH,MAAA,OAAO,EAAE,UAAU,WAAA,EAAY;AAAA,IACjC,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,UAAU,SAAA,EAAU;AAAA,IAC/B,KAAK,MAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,UAAU,MAAA,EAAO;AAAA,IAC5B,KAAK,QAAA;AAAA,IACL,KAAK,kBAAA;AAAA,IACL,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,UAAU,QAAA,EAAS;AAAA,IAC9B;AACE,MAAA,OAAO,EAAE,UAAU,KAAA,EAAM;AAAA;AAE/B;AAQA,SAAS,SAAS,OAAA,EAA6B;AAC7C,EAAA,MAAM,CAAC,KAAA,EAAO,MAAM,CAAA,GAAI,OAAA,CAAQ,MAAM,GAAG,CAAA;AACzC,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,MAAM,OAAA,GAAU,cAAc,KAAK,CAAA;AACnC,IAAA,OAAO,EAAE,EAAA,EAAI,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,GAAA,EAAK,OAAA,EAAQ;AAAA,EAC/F;AACA,EAAA,MAAM,SAAA,GAAY,SAAS,KAAK,CAAA;AAChC,EAAA,MAAM,OAAA,GAAU,cAAc,MAAM,CAAA;AACpC,EAAA,OAAO,EAAE,EAAA,EAAI,OAAA,EAAS,IAAA,EAAM,UAAA,EAAY,SAAS,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,GAAA,EAAK,OAAA,EAAQ;AAC1F;AAEA,SAAS,SAAS,KAAA,EAAuB;AACvC,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC1B;AAEA,SAAS,cAAc,KAAA,EAAuB;AAC5C,EAAA,MAAM,IAAA,GAAO,SAAS,KAAK,CAAA;AAC3B,EAAA,IAAI,CAAC,GAAA,CAAI,IAAA,CAAK,KAAK,GAAG,OAAO,IAAA;AAC7B,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,UAAA,CAAY,CAAA;AACxC,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,EAAG,OAAO,IAAA;AAC5B,EAAA,OAAO,IAAI,KAAK,CAAA,GAAI,KAAQ,EAAE,WAAA,EAAY,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACzD;AAKO,SAAS,UAAU,GAAA,EAAwC;AAChE,EAAA,MAAM,OAAQ,OAAO,GAAA,KAAQ,WAAW,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,GAAI,GAAA;AAC1D,EAAA,MAAM,KAAA,GAAmB,IAAA,CAAK,SAAA,IAAa,EAAC;AAC5C,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,EAAc,UAAA,IAAc,EAAC;AAGrD,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAiC;AACpD,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,MAAA,IAAU,EAAC,EAAG;AAClC,IAAA,IAAI,CAAC,EAAE,SAAA,IAAa,CAAC,EAAE,SAAA,IAAa,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,EAAU;AACjE,IAAA,IAAI,MAAA,GAAS,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,SAAS,CAAA;AACnC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAA,uBAAa,GAAA,EAAI;AACjB,MAAA,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,SAAA,EAAW,MAAM,CAAA;AAAA,IAChC;AACA,IAAA,IAAI,CAAC,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,SAAS,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,SAAA,EAAW,CAAA,CAAE,KAAK,CAAA;AAAA,EAC/D;AACA,EAAA,MAAM,OAAA,GAAU,CAAC,IAAA,EAAc,IAAA,GAAO,cAAA,KACpC,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,EAAG,GAAA,CAAI,IAAI,CAAA,IAAK,IAAA;AACjC,EAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KAAyB;AAC7C,IAAA,MAAM,QAAA,GAAW,QAAQ,IAAI,CAAA;AAC7B,IAAA,OAAO,QAAA,GAAW,eAAA,CAAgB,QAAQ,CAAA,GAAI,SAAS,IAAI,CAAA;AAAA,EAC7D,CAAA;AAGA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,EAAC;AAC9B,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AACvC,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,MAAM,IAAA,GAAO,CAAA,CAAE,cAAA,IAAkB,EAAC;AAClC,IAAA,MAAM,IAAA,GAAO,KAAK,WAAW,CAAA;AAC7B,IAAA,MAAM,OAAA,GAAU,KAAK,cAAc,CAAA;AACnC,IAAA,IAAI,OAAO,SAAS,QAAA,IAAY,OAAO,YAAY,QAAA,IAAY,SAAA,CAAU,IAAI,CAAA,KAAM,QAAA,EAAU;AAC3F,MAAA,cAAA,CAAe,IAAI,OAAO,CAAA;AAAA,IAC5B;AAAA,EACF;AAGA,EAAA,MAAM,WAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,QAAA,IAAY,EAAC,EAAG;AACpC,IAAA,MAAM,YAAA,GAAe,aAAA,CAAc,CAAA,CAAE,UAAA,EAAY,eAAe,CAAA;AAChE,IAAA,MAAM,OAAA,GACJ,YAAA,KAAiB,OAAA,IAAW,YAAA,KAAiB,WAAW,YAAA,GAAe,IAAA;AACzE,IAAA,MAAM,UAAA,GACJ,EAAE,UAAA,KAAe,SAAA,IAAa,EAAE,UAAA,KAAe,UAAA,GAAa,EAAE,UAAA,GAAa,IAAA;AAC7E,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,CAAA,CAAE,QAAQ,CAAA;AACnC,IAAA,MAAM,WAAW,CAAC,KAAA,CAAM,eAAe,cAAA,CAAe,GAAA,CAAI,EAAE,IAAI,CAAA;AAChE,IAAA,QAAA,CAAS,CAAA,CAAE,IAAI,CAAA,GAAI;AAAA,MACjB,IAAI,CAAA,CAAE,IAAA;AAAA,MACN,OAAO,CAAA,CAAE,IAAA;AAAA,MACT,KAAA,EAAO,YAAA,CAAa,CAAA,CAAE,IAAI,CAAA;AAAA,MAC1B,OAAA;AAAA,MACA,UAAA;AAAA,MACA,QAAA,EAAU,KAAA;AAAA,MACV,QAAA,EAAU,MAAM,WAAA,KAAgB,UAAA;AAAA,MAChC,QAAA,EAAU,QAAA,GAAW,QAAA,GAAW,KAAA,CAAM,QAAA;AAAA,MACtC,WAAA,EAAa,QAAA,GAAW,QAAA,GAAW,KAAA,CAAM;AAAA,KAC3C;AAAA,EACF;AACA,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,GAAI,KAAA,CAAM,QAAA,IAAY,EAAC;AAAA,IACvB,GAAI,KAAA,CAAM,UAAA,IAAc,EAAC;AAAA,IACzB,GAAI,KAAA,CAAM,aAAA,IAAiB,EAAC;AAAA,IAC5B,GAAI,KAAA,CAAM,OAAA,IAAW;AAAC,GACxB;AACA,EAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,IAAA,IAAI,CAAC,CAAA,CAAE,IAAA,IAAQ,QAAA,CAAS,CAAA,CAAE,IAAI,CAAA,EAAG;AACjC,IAAA,QAAA,CAAS,CAAA,CAAE,IAAI,CAAA,GAAI;AAAA,MACjB,IAAI,CAAA,CAAE,IAAA;AAAA,MACN,OAAO,CAAA,CAAE,IAAA;AAAA,MACT,KAAA,EAAO,YAAA,CAAa,CAAA,CAAE,IAAI,CAAA;AAAA,MAC1B,OAAA,EAAS,IAAA;AAAA,MACT,UAAA,EAAY,IAAA;AAAA,MACZ,QAAA,EAAU,IAAA;AAAA,MACV,QAAA,EAAU;AAAA,KACZ;AAAA,EACF;AACA,EAAA,MAAM,eAAe,IAAI,GAAA;AAAA,IAAA,CACtB,KAAA,CAAM,UAAA,IAAc,EAAC,EAAG,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI;AAAA,GACzE;AAGA,EAAA,MAAM,QAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,KAAA,IAAS,EAAC,EAAG;AACjC,IAAA,IAAI,CAAC,EAAE,IAAA,EAAM;AACb,IAAA,MAAM,OAAA,GAAU,CAAA,CAAE,2BAAA,GAA8B,CAAC,KAAK,CAAA,CAAE,IAAA;AACxD,IAAA,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI;AAAA,MACd,IAAI,CAAA,CAAE,IAAA;AAAA,MACN,OAAA;AAAA,MACA,OAAO,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,GACvB,QAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,SAAS,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,GAC1C,UAAU,OAAO;AAAA,KACvB;AAAA,EACF;AAGA,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAuB;AAC1C,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,MAAA,IAAU,IAAI,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,CAAC,CAAA;AACxD,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,EAAA,KAAA,MAAW,EAAA,IAAM,KAAA,CAAM,aAAA,IAAiB,EAAC,UAAW,GAAA,CAAI,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,SAAS,CAAA;AAClF,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAoB;AAC1C,EAAA,CAAC,KAAA,CAAM,MAAA,IAAU,EAAC,EAAG,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,CAAC,CAAC,CAAA;AAEjE,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,IAAY,EAAC;AACpC,EAAA,MAAM,aAA8B,EAAC;AACrC,EAAA,MAAM,oBAAwC,EAAC;AAC/C,EAAA,MAAM,mBAAsC,EAAC;AAC7C,EAAA,MAAM,mBAAsC,EAAC;AAE7C,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAsB;AAE9C,EAAA,MAAM,mBAAA,uBAA0B,GAAA,EAAoB;AAEpD,EAAA,MAAM,WAAA,GAAc,CAAC,SAAA,KAAkC;AACrD,IAAA,MAAM,KAAA,GAAQ,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,SAAS,CAAA,GAAI,MAAA;AAClD,IAAA,MAAM,UAAA,GAAa,SAAA,GAAY,OAAA,CAAQ,SAAS,CAAA,GAAI,IAAA;AACpD,IAAA,MAAM,MAAA,GAAS,mBAAmB,UAAU,CAAA;AAC5C,IAAA,MAAM,OAAA,GAAU,OAAO,QAAA,IAAY,IAAA;AACnC,IAAA,MAAM,QAAA,GAAW,UAAU,QAAA,CAAS,OAAO,IAAI,SAAA,GAAY,QAAA,CAAS,SAAS,CAAA,GAAI,SAAA;AACjF,IAAA,MAAM,WAAW,UAAA,GAAa,eAAA,CAAgB,KAAK,UAAU,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA;AACtE,IAAA,OAAO;AAAA,MACL,OAAA;AAAA,MACA,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,KAAA,EAAO,OAAO,KAAA,IAAS,QAAA;AAAA,MACvB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,KAAA,EAAO,QAAA,GACH,MAAA,CAAO,QAAQ,CAAA,GACf,YACG,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA,IAAK,MAAA,GAC9B;AAAA,KACR;AAAA,EACF,CAAA;AAEA,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,IAAI,CAAA,CAAE,yBAAyB,YAAA,EAAc;AAC7C,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,YAAY,SAAS,CAAA;AAClC,IAAA,IAAI,SAAA,IAAa,CAAC,mBAAA,CAAoB,GAAA,CAAI,SAAS,GAAG,mBAAA,CAAoB,GAAA,CAAI,SAAA,EAAW,CAAA,CAAE,IAAI,CAAA;AAC/F,IAAA,UAAA,CAAW,IAAA,CAAK;AAAA,MACd,IAAI,CAAA,CAAE,IAAA;AAAA,MACN,SAAA,EAAW,EAAA;AAAA,MACX,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,eAAe,IAAA,CAAK,KAAA;AAAA,MACpB,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,OAAO,IAAA,CAAK;AAAA,KACb,CAAA;AACD,IAAA,iBAAA,CAAkB,IAAA,CAAK;AAAA,MACrB,IAAI,CAAA,CAAE,IAAA;AAAA,MACN,SAAA,EAAW,EAAA;AAAA,MACX,SAAS,CAAA,CAAE,IAAA;AAAA,MACX,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,aAAa,CAAA,CAAE;AAAA,KAChB,CAAA;AACD,IAAA,KAAA,MAAW,CAAA,IAAK,CAAA,CAAE,aAAA,IAAiB,EAAC,EAAG;AACrC,MAAA,IAAI,CAAC,CAAA,CAAE,MAAA,IAAU,CAAC,EAAE,MAAA,EAAQ;AAC5B,MAAA,KAAA,MAAW,IAAA,IAAQ,CAAA,CAAE,MAAA,KAAW,WAAA,GAAc,CAAC,CAAA,CAAE,MAAM,CAAA,GAAI,CAAC,CAAA,CAAE,MAAA,EAAQ,CAAA,CAAE,MAAM,CAAA,EAAG;AAC/E,QAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA;AACjC,QAAA,IAAI,CAAC,MAAM,WAAA,CAAY,GAAA,CAAI,MAAM,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,aAAA,IAChC,CAAC,KAAK,QAAA,CAAS,CAAA,CAAE,IAAI,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,CAAA,CAAE,IAAI,CAAA;AAAA,MACnD;AACA,MAAA,IAAI,CAAA,CAAE,WAAW,WAAA,EAAa;AAC9B,MAAA,MAAM,SAAA,GAAY,aAAA,CAAc,CAAA,CAAE,UAAA,EAAY,qBAAqB,CAAA;AACnE,MAAA,MAAM,aAAA,GAAgB,OAAO,SAAA,KAAc,QAAA,GAAW,SAAA,GAAY,IAAA;AAClE,MAAA,MAAM,aAAA,GACJ,iBAAiB,aAAA,KAAkB,cAAA,GAAiB,QAAQ,CAAA,CAAE,MAAA,EAAQ,aAAa,CAAA,GAAI,IAAA;AACzF,MAAA,gBAAA,CAAiB,IAAA,CAAK;AAAA,QACpB,QAAQ,CAAA,CAAE,MAAA;AAAA,QACV,OAAO,CAAA,CAAE,MAAA;AAAA,QACT,KAAA,EAAO,QAAA,CAAS,CAAA,CAAE,KAAK,CAAA,IAAK,CAAA;AAAA,QAC5B,MAAM,IAAA,CAAK,OAAA;AAAA,QACX,WAAW,CAAA,CAAE,IAAA;AAAA,QACb,cAAA,EAAgB,aAAA,GAAgB,eAAA,CAAgB,aAAa,CAAA,GAAI,IAAA;AAAA,QACjE,kBAAA,EAAoB;AAAA,OACrB,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,IAAI,CAAA,CAAE,yBAAyB,WAAA,EAAa;AAC5C,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA;AACpC,IAAA,MAAM,SAAA,GAAA,CAAa,SAAA,IAAa,mBAAA,CAAoB,GAAA,CAAI,SAAS,CAAA,KAAM,IAAA;AACvE,IAAA,MAAM,UAAU,SAAA,GAAa,MAAA,CAAO,IAAI,SAAS,CAAA,EAAG,YAAY,IAAA,GAAQ,IAAA;AACxE,IAAA,KAAA,MAAW,CAAA,IAAK,CAAA,CAAE,aAAA,IAAiB,EAAC,EAAG;AACrC,MAAA,IAAI,CAAC,EAAE,MAAA,IAAU,CAAC,EAAE,MAAA,IAAU,CAAA,CAAE,WAAW,WAAA,EAAa;AACxD,MAAA,gBAAA,CAAiB,IAAA,CAAK;AAAA,QACpB,QAAQ,CAAA,CAAE,MAAA;AAAA,QACV,OAAO,CAAA,CAAE,MAAA;AAAA,QACT,QAAQ,QAAA,CAAS,aAAA,CAAc,EAAE,UAAA,EAAY,aAAa,CAAC,CAAA,IAAK,CAAA;AAAA,QAChE,KAAA,EAAO,QAAA,CAAS,CAAA,CAAE,KAAK,CAAA,IAAK,CAAA;AAAA,QAC5B,IAAA,EAAM,OAAA;AAAA,QACN;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAGA,EAAA,MAAM,UAAsC,EAAC;AAC7C,EAAA,MAAM,MAAc,EAAC;AACrB,EAAA,IAAI,cAAA,GAAgC,IAAA;AACpC,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,MAAM,IAAA,GAAO,CAAA,CAAE,cAAA,IAAkB,EAAC;AAClC,IAAA,MAAM,OAAA,GAAU,KAAK,cAAc,CAAA;AACnC,IAAA,MAAM,aAAA,GAAgB,KAAK,aAAa,CAAA;AACxC,IAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAO,kBAAkB,QAAA,EAAU;AACtE,IAAA,IAAI,CAAC,QAAQ,aAAa,CAAA,UAAW,aAAa,CAAA,GAAI,SAAS,aAAa,CAAA;AAC5E,IAAA,MAAM,IAAA,GAAO,OAAO,IAAA,CAAK,WAAW,MAAM,QAAA,GAAY,IAAA,CAAK,WAAW,CAAA,GAAe,IAAA;AACrF,IAAA,MAAMA,OAAAA,GAAS,OAAO,IAAA,CAAK,aAAa,MAAM,QAAA,GAAY,IAAA,CAAK,aAAa,CAAA,GAAe,IAAA;AAC3F,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,UAAA,GAAa,CAAC,CAAA;AAC9B,IAAA,MAAM,MAAM,KAAA,EAAO,KAAA;AACnB,IAAA,MAAM,OAAA,GACJ,SAAS,OAAO,CAAA,EAAG,gBAAgB,MAAA,IAAa,QAAA,CAAS,OAAO,CAAA,EAAG,QAAA,KAAa,SAAA;AAClF,IAAA,MAAM,QAAQ,OAAA,IAAW,OAAO,QAAQ,QAAA,GAAW,QAAA,CAAS,GAAG,CAAA,GAAI,IAAA;AACnE,IAAA,MAAM,SAAA,GAAY,UAAU,IAAA,IAAQ,GAAA,KAAQ,UAAa,GAAA,KAAQ,IAAA,GAAO,MAAA,CAAO,GAAG,CAAA,GAAI,IAAA;AACtF,IAAA,IAAI,OAAA,KAAY,eAAA,IAAmB,SAAA,IAAa,CAAC,gBAAgB,cAAA,GAAiB,SAAA;AAClF,IAAA,MAAM,cAAc,KAAA,EAAO,QAAA;AAC3B,IAAA,MAAM,QAAA,GACJ,OAAO,WAAA,KAAgB,QAAA,GACnB,MAAA,CAAO,WAAW,CAAA,GAClB,OAAO,WAAA,KAAgB,QAAA,GACrB,WAAA,GACA,IAAA;AAER,IAAA,MAAM,aAAmC,EAAC;AAC1C,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AACjD,MAAA,IAAI,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,EAAG;AAC5B,MAAA,MAAM,QAAA,GAAW,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,IAAK,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA;AAC5F,MAAA,MAAM,UAAA,GAAa,WAAY,MAAA,GAAoB,IAAA;AACnD,MAAA,MAAM,UAAA,GAAa,WACf,IAAA,GACA,MAAA,KAAW,QAAQ,MAAA,KAAW,MAAA,GAC5B,IAAA,GACA,MAAA,CAAO,MAAM,CAAA;AACnB,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACd,IAAA;AAAA,QACA,MAAA,EAAQ,UAAA;AAAA,QACR,WAAW,QAAA,CAAS,IAAI,CAAA,EAAG,KAAA,IAAS,SAAS,IAAI,CAAA;AAAA,QACjD,WAAA,EAAa,aACR,QAAA,CAAS,UAAU,GAAG,KAAA,IAAS,QAAA,CAAS,UAAU,CAAA,GAClD,UAAA,IAAc,EAAA;AAAA,QACnB,QAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AACA,IAAA,MAAM,QAAA,GAAW,WAAA,CAAY,GAAA,CAAI,OAAO,KAAK,EAAC;AAC9C,IAAA,GAAA,CAAI,IAAA,CAAK;AAAA,MACP,IAAI,CAAA,CAAE,IAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAA,EAAQ,aAAA;AAAA,MACR,IAAA;AAAA,MACA,MAAA,EAAAA,OAAAA;AAAA,MACA,OAAA,EAAS,QAAA,CAAS,CAAC,CAAA,IAAK,IAAA;AAAA,MACxB,UAAU,QAAA,CAAS,MAAA,GAAS,CAAC,GAAG,QAAQ,CAAA,GAAI,MAAA;AAAA,MAC5C,KAAA;AAAA,MACA,SAAA;AAAA,MACA,WAAA,EAAa,IAAA;AAAA,MACb,QAAA;AAAA,MACA,UAAA,EAAY,UAAA,CAAW,MAAA,GAAS,UAAA,GAAa;AAAA,KAC9C,CAAA;AAAA,EACH;AAGA,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,QAAA,GAAW,CAAC,GAAG,IAAA,IAAQ,IAAA;AAChD,EAAA,MAAM,SAA4B,UAAA,GAC9B;AAAA,IACE,EAAA,EAAI,UAAA;AAAA,IACJ,IAAA,EAAM,cAAA,IAAkB,QAAA,CAAS,UAAU,CAAA;AAAA,IAC3C,SAAA,EAAW,cAAA;AAAA,IACX,OAAA,EAAS;AAAA,GACX,GACA,IAAA;AACJ,EAAA,MAAM,SAAA,GAAY,WAAW,GAAA,IAAO,IAAA;AACpC,EAAA,MAAM,QAAA,GAAW,SAAA,GACZ,SAAA,CAAU,OAAA,CAAQ,OAAO,EAAE,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,EAAI,IAAK,IAAA,GACjD,MAAM,IAAA,IAAQ,IAAA;AAEnB,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,iBAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA,EAAO,GAAA;AAAA,IACP,QAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,eAAA,CAAgB,GAAA,EAAsB,MAAA,GAAS,WAAA,EAA4B;AACzF,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,IAAA,EAAM,YAAY,SAAA,CAAU,GAAG;AAAA,GACjC;AACF;;;ACrhBO,SAAS,mBAAmB,GAAA,EAAmC;AACpE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,IAAA;AAC5C,EAAA,IAAI,cAAA,CAAe,GAAG,CAAA,EAAG,OAAO,MAAA;AAChC,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,IAAI,cAAc,CAAA,IAAK,QAAA,IAAY,CAAA,IAAK,KAAA,IAAS,GAAG,OAAO,OAAA;AAC3D,EAAA,OAAO,IAAA;AACT;AAGA,eAAsB,oBACpB,GAAA,EAC6D;AAC7D,EAAA,MAAM,OAAQ,OAAO,GAAA,KAAQ,WAAW,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,GAAI,GAAA;AAC1D,EAAA,MAAM,MAAA,GAAS,mBAAmB,IAAI,CAAA;AACtC,EAAA,IAAI,MAAA,KAAW,QAAQ,OAAO,EAAE,QAAQ,MAAA,EAAQ,SAAA,CAAU,IAAI,CAAA,EAAE;AAChE,EAAA,IAAI,MAAA,KAAW,SAAS,OAAO,EAAE,QAAQ,MAAA,EAAQ,MAAM,WAAA,CAAY,IAAI,CAAA,EAAE;AACzE,EAAA,MAAM,IAAI,MAAM,4EAA4E,CAAA;AAC9F","file":"index.js","sourcesContent":["/**\n * The `tavi.json` adapter — offline, no backend, no auth.\n *\n * A filing as a **Project Tavi compiled model** (XBRL International, PWD\n * 2026-09-01): one JSON object model carrying the taxonomy objects and the\n * report objects together, fully resolved. It is the second of xbrlkit's JSON\n * projections beside the holon, and the two carry the same facts, so a report\n * renders identically from either. Unlike the holon there is no RDF step: the\n * model is walked directly, which is also why this adapter is synchronous.\n *\n * The one thing Tavi has that the normalized model must be *given* is the\n * section partition. A holon carries Information Blocks and fact sets; a Tavi\n * carries presentation networks under groups (the extended link roles). Each\n * presentation network becomes a section whose fact set is the network itself,\n * and a fact belongs to every network that presents its concept — the same\n * rule the SEC adapter applies per structure. The pivot's dimensional scope\n * then keeps a segment breakdown out of the face statement.\n *\n * Periods are normalized to the holon's human-facing dates: Tavi writes ISO\n * intervals of exclusive-end dateTimes (`2025-01-01T00:00:00` is the close of\n * 2024-12-31), older emitters wrote inclusive dates; both land as the same\n * `PeriodInfo`.\n */\nimport { humanize, stripRoleSuffix } from '../constants'\nimport type {\n BalanceType,\n CalcAssociation,\n DimensionQualifier,\n ElementInfo,\n EntityInfo,\n Fact,\n InformationBlock,\n NormalizedReport,\n NumericKind,\n PeriodInfo,\n PeriodType,\n PresAssociation,\n StructureInfo,\n UnitInfo,\n} from '../model'\nimport { parseStructureName } from '../sections'\nimport type { ReportAdapter } from './types'\n\n// ── The document, as far as this adapter reads it ───────────────────────────\n\ninterface TaviProperty {\n property: string\n value?: unknown\n}\ninterface TaviNamed {\n name: string\n}\ninterface TaviConcept extends TaviNamed {\n dataType?: string | null\n periodType?: string | null\n properties?: TaviProperty[]\n}\ninterface TaviDimension extends TaviNamed {\n domainClass?: string | null\n}\ninterface TaviUnit extends TaviNamed {\n dataType?: string\n compositeUnitRepresentation?: string[]\n}\ninterface TaviLabel {\n forObject: string\n labelType: string\n value: string\n language?: string\n}\ninterface TaviRelationship {\n source: string\n target: string\n order?: number\n properties?: TaviProperty[]\n}\ninterface TaviNetwork extends TaviNamed {\n relationshipTypeName?: string\n relationships?: TaviRelationship[]\n roots?: string[]\n}\ninterface TaviGroup extends TaviNamed {\n groupURI?: string\n}\ninterface TaviGroupContent {\n groupName: string\n forObject: string\n}\ninterface TaviFactValue {\n value?: unknown\n decimals?: unknown\n}\ninterface TaviFact extends TaviNamed {\n factDimensions?: Record<string, unknown>\n factValues?: TaviFactValue[]\n}\ninterface TaviModel {\n name?: string\n modelType?: string\n properties?: TaviProperty[]\n entities?: TaviNamed[]\n units?: TaviUnit[]\n concepts?: TaviConcept[]\n headings?: TaviNamed[]\n dimensions?: TaviDimension[]\n domainClasses?: TaviNamed[]\n members?: TaviNamed[]\n labels?: TaviLabel[]\n networks?: TaviNetwork[]\n groups?: TaviGroup[]\n groupContents?: TaviGroupContent[]\n facts?: TaviFact[]\n}\n\n/** A Tavi document: the envelope and the model. */\nexport interface TaviDocument {\n documentInfo?: {\n documentType?: string\n namespaces?: Record<string, string>\n description?: string\n }\n xbrlModel?: TaviModel\n}\n\nconst TAVI_DOCUMENT_TYPE = /xbrl\\.org\\/(PWD|20\\d\\d)\\//\nconst PRESENTATION = 'xbrl:parent-child'\nconst CALCULATION = 'xbrl:summation-item'\nconst ROOT_SOURCE = 'xbrl:rootSource'\n/** The fact aspects that are not taxonomy dimensions. */\nconst CORE_ASPECTS = new Set([\n 'xbrl:concept',\n 'xbrl:period',\n 'xbrl:entity',\n 'xbrl:unit',\n 'xbrl:language',\n])\nconst STANDARD_LABEL = 'xbrl:label'\nconst REGISTRANT_NAME = 'dei:EntityRegistrantName'\n\n/** Whether a parsed document is a Tavi model (a `documentInfo.documentType` under xbrl.org, or an `xbrlModel` report). */\nexport function isTaviDocument(doc: unknown): doc is TaviDocument {\n if (!doc || typeof doc !== 'object') return false\n const d = doc as TaviDocument\n if (!d.xbrlModel || typeof d.xbrlModel !== 'object') return false\n const type = d.documentInfo?.documentType\n return (\n (typeof type === 'string' && TAVI_DOCUMENT_TYPE.test(type)) ||\n d.xbrlModel.modelType === 'xbrl:report'\n )\n}\n\n// ── Small readers ───────────────────────────────────────────────────────────\n\nfunction propertyValue(props: TaviProperty[] | undefined, name: string): unknown {\n return props?.find((p) => p.property === name)?.value\n}\n\nfunction toNumber(raw: unknown): number | null {\n if (typeof raw === 'number') return Number.isFinite(raw) ? raw : null\n if (typeof raw === 'string' && raw.trim() !== '') {\n const n = Number(raw)\n return Number.isNaN(n) ? null : n\n }\n return null\n}\n\nfunction localName(qname: string): string {\n const i = qname.indexOf(':')\n return i >= 0 ? qname.slice(i + 1) : qname\n}\n\n/**\n * A Tavi datatype → the holon's `rs:itemType` vocabulary and the numeric kind\n * that drives formatting. Share counts have no built-in Tavi type (the\n * emitter records them as a gap), so they are recognized from the unit their\n * facts carry instead — see `sharesConcepts`.\n */\nfunction itemTypeOf(dataType: string | null | undefined): {\n itemType?: string\n numericKind?: NumericKind\n} {\n if (!dataType) return {}\n const local = localName(dataType)\n switch (local) {\n case 'monetary':\n return { itemType: 'monetary', numericKind: 'monetary' }\n case 'perShare':\n return { itemType: 'perShare', numericKind: 'perShare' }\n case 'percent':\n return { itemType: 'percent', numericKind: 'percent' }\n case 'pure':\n return { itemType: 'pure', numericKind: 'pure' }\n case 'sharesType':\n case 'shares':\n return { itemType: 'shares', numericKind: 'shares' }\n case 'integer':\n case 'int':\n case 'long':\n case 'nonNegativeInteger':\n return { itemType: 'integer', numericKind: 'integer' }\n case 'decimal':\n case 'float':\n case 'double':\n return { itemType: 'decimal' }\n case 'textBlock':\n return { itemType: 'textBlock' }\n case 'boolean':\n return { itemType: 'boolean' }\n case 'date':\n case 'dateTime':\n return { itemType: 'date' }\n case 'string':\n case 'normalizedString':\n case 'token':\n return { itemType: 'string' }\n default:\n return { itemType: local }\n }\n}\n\n/**\n * A Tavi period literal as the holon's human-facing dates. An interval is\n * `start/end`; an instant is one value. A dateTime is exclusive (Tavi's\n * `xbrlr:periodString` form): the day before is the date meant. A bare date\n * (older emitters) is inclusive already.\n */\nfunction periodOf(literal: string): PeriodInfo {\n const [first, second] = literal.split('/')\n if (second === undefined) {\n const instant = inclusiveDate(first)\n return { id: literal, type: 'instant', instant, startDate: null, endDate: null, end: instant }\n }\n const startDate = datePart(first)\n const endDate = inclusiveDate(second)\n return { id: literal, type: 'duration', instant: null, startDate, endDate, end: endDate }\n}\n\nfunction datePart(value: string): string {\n return value.slice(0, 10)\n}\n\nfunction inclusiveDate(value: string): string {\n const date = datePart(value)\n if (!/T/.test(value)) return date\n const t = Date.parse(`${date}T00:00:00Z`)\n if (Number.isNaN(t)) return date\n return new Date(t - 86400000).toISOString().slice(0, 10)\n}\n\n// ── The parse ───────────────────────────────────────────────────────────────\n\n/** Parse a `tavi.json` document (string or parsed object) into the model. */\nexport function parseTavi(doc: string | object): NormalizedReport {\n const json = (typeof doc === 'string' ? JSON.parse(doc) : doc) as TaviDocument\n const model: TaviModel = json.xbrlModel ?? {}\n const namespaces = json.documentInfo?.namespaces ?? {}\n\n // ── Labels: object → label type → text (the first of each type wins) ──\n const labels = new Map<string, Map<string, string>>()\n for (const l of model.labels ?? []) {\n if (!l.forObject || !l.labelType || typeof l.value !== 'string') continue\n let byType = labels.get(l.forObject)\n if (!byType) {\n byType = new Map()\n labels.set(l.forObject, byType)\n }\n if (!byType.has(l.labelType)) byType.set(l.labelType, l.value)\n }\n const labelOf = (name: string, type = STANDARD_LABEL): string | null =>\n labels.get(name)?.get(type) ?? null\n const displayLabel = (name: string): string => {\n const standard = labelOf(name)\n return standard ? stripRoleSuffix(standard) : humanize(name)\n }\n\n // ── Facts, first pass: the units concepts are measured in ──\n const facts = model.facts ?? []\n const sharesConcepts = new Set<string>()\n for (const f of facts) {\n const dims = f.factDimensions ?? {}\n const unit = dims['xbrl:unit']\n const concept = dims['xbrl:concept']\n if (typeof unit === 'string' && typeof concept === 'string' && localName(unit) === 'shares') {\n sharesConcepts.add(concept)\n }\n }\n\n // ── Elements: concepts, then the structural objects ──\n const elements: Record<string, ElementInfo> = {}\n for (const c of model.concepts ?? []) {\n const balanceValue = propertyValue(c.properties, 'xbrla:balance')\n const balance: BalanceType | null =\n balanceValue === 'debit' || balanceValue === 'credit' ? balanceValue : null\n const periodType: PeriodType | null =\n c.periodType === 'instant' || c.periodType === 'duration' ? c.periodType : null\n const typed = itemTypeOf(c.dataType)\n const asShares = !typed.numericKind && sharesConcepts.has(c.name)\n elements[c.name] = {\n id: c.name,\n qname: c.name,\n label: displayLabel(c.name),\n balance,\n periodType,\n abstract: false,\n monetary: typed.numericKind === 'monetary',\n itemType: asShares ? 'shares' : typed.itemType,\n numericKind: asShares ? 'shares' : typed.numericKind,\n }\n }\n const structural = [\n ...(model.headings ?? []),\n ...(model.dimensions ?? []),\n ...(model.domainClasses ?? []),\n ...(model.members ?? []),\n ]\n for (const s of structural) {\n if (!s.name || elements[s.name]) continue\n elements[s.name] = {\n id: s.name,\n qname: s.name,\n label: displayLabel(s.name),\n balance: null,\n periodType: null,\n abstract: true,\n monetary: false,\n }\n }\n const explicitAxes = new Set(\n (model.dimensions ?? []).filter((d) => d.domainClass).map((d) => d.name)\n )\n\n // ── Units ──\n const units: Record<string, UnitInfo> = {}\n for (const u of model.units ?? []) {\n if (!u.name) continue\n const measure = u.compositeUnitRepresentation?.[0] ?? u.name\n units[u.name] = {\n id: u.name,\n measure,\n label: measure.includes('/')\n ? measure.split('/').map(localName).join('/')\n : localName(measure),\n }\n }\n\n // ── Sections: one per presentation network, titled by its group's definition ──\n const groups = new Map<string, TaviGroup>()\n for (const g of model.groups ?? []) groups.set(g.name, g)\n const groupOf = new Map<string, string>()\n for (const gc of model.groupContents ?? []) groupOf.set(gc.forObject, gc.groupName)\n const groupIndex = new Map<string, number>()\n ;(model.groups ?? []).forEach((g, i) => groupIndex.set(g.name, i))\n\n const networks = model.networks ?? []\n const structures: StructureInfo[] = []\n const informationBlocks: InformationBlock[] = []\n const presAssociations: PresAssociation[] = []\n const calcAssociations: CalcAssociation[] = []\n /** concept → the presentation networks that present it */\n const presentedIn = new Map<string, string[]>()\n /** group → its first presentation network (the structure a calc network attaches to) */\n const presentationOfGroup = new Map<string, string>()\n\n const sectionMeta = (groupName: string | undefined) => {\n const group = groupName ? groups.get(groupName) : undefined\n const definition = groupName ? labelOf(groupName) : null\n const parsed = parseStructureName(definition)\n const roleUri = group?.groupURI ?? null\n const fallback = roleUri ? humanize(roleUri) : groupName ? humanize(groupName) : 'Section'\n const sortCode = definition ? /^\\s*(\\d+)\\s*-/.exec(definition)?.[1] : undefined\n return {\n roleUri,\n definition: parsed.definition,\n title: parsed.title ?? fallback,\n kind: parsed.kind,\n order: sortCode\n ? Number(sortCode)\n : groupName\n ? (groupIndex.get(groupName) ?? undefined)\n : undefined,\n }\n }\n\n for (const n of networks) {\n if (n.relationshipTypeName !== PRESENTATION) continue\n const groupName = groupOf.get(n.name)\n const meta = sectionMeta(groupName)\n if (groupName && !presentationOfGroup.has(groupName)) presentationOfGroup.set(groupName, n.name)\n structures.push({\n id: n.name,\n blockType: '',\n roleUri: meta.roleUri,\n structureName: meta.title,\n definition: meta.definition,\n kind: meta.kind,\n order: meta.order,\n })\n informationBlocks.push({\n id: n.name,\n blockType: '',\n factSet: n.name,\n label: meta.title,\n structureId: n.name,\n })\n for (const r of n.relationships ?? []) {\n if (!r.source || !r.target) continue\n for (const node of r.source === ROOT_SOURCE ? [r.target] : [r.source, r.target]) {\n const list = presentedIn.get(node)\n if (!list) presentedIn.set(node, [n.name])\n else if (!list.includes(n.name)) list.push(n.name)\n }\n if (r.source === ROOT_SOURCE) continue\n const preferred = propertyValue(r.properties, 'xbrl:preferredLabel')\n const preferredType = typeof preferred === 'string' ? preferred : null\n const preferredText =\n preferredType && preferredType !== STANDARD_LABEL ? labelOf(r.target, preferredType) : null\n presAssociations.push({\n parent: r.source,\n child: r.target,\n order: toNumber(r.order) ?? 0,\n role: meta.roleUri,\n structure: n.name,\n preferredLabel: preferredText ? stripRoleSuffix(preferredText) : null,\n preferredLabelRole: preferredType,\n })\n }\n }\n for (const n of networks) {\n if (n.relationshipTypeName !== CALCULATION) continue\n const groupName = groupOf.get(n.name)\n const structure = (groupName && presentationOfGroup.get(groupName)) ?? null\n const roleUri = groupName ? (groups.get(groupName)?.groupURI ?? null) : null\n for (const r of n.relationships ?? []) {\n if (!r.source || !r.target || r.source === ROOT_SOURCE) continue\n calcAssociations.push({\n parent: r.source,\n child: r.target,\n weight: toNumber(propertyValue(r.properties, 'xbrl:weight')) ?? 1,\n order: toNumber(r.order) ?? 0,\n role: roleUri,\n structure,\n })\n }\n }\n\n // ── Facts ──\n const periods: Record<string, PeriodInfo> = {}\n const out: Fact[] = []\n let registrantName: string | null = null\n for (const f of facts) {\n const dims = f.factDimensions ?? {}\n const element = dims['xbrl:concept']\n const periodLiteral = dims['xbrl:period']\n if (typeof element !== 'string' || typeof periodLiteral !== 'string') continue\n if (!periods[periodLiteral]) periods[periodLiteral] = periodOf(periodLiteral)\n const unit = typeof dims['xbrl:unit'] === 'string' ? (dims['xbrl:unit'] as string) : null\n const entity = typeof dims['xbrl:entity'] === 'string' ? (dims['xbrl:entity'] as string) : null\n const first = f.factValues?.[0]\n const raw = first?.value\n const numeric =\n elements[element]?.numericKind !== undefined || elements[element]?.itemType === 'decimal'\n const value = numeric || typeof raw === 'number' ? toNumber(raw) : null\n const textValue = value === null && raw !== undefined && raw !== null ? String(raw) : null\n if (element === REGISTRANT_NAME && textValue && !registrantName) registrantName = textValue\n const decimalsRaw = first?.decimals\n const decimals =\n typeof decimalsRaw === 'number'\n ? String(decimalsRaw)\n : typeof decimalsRaw === 'string'\n ? decimalsRaw\n : null\n\n const dimensions: DimensionQualifier[] = []\n for (const [axis, member] of Object.entries(dims)) {\n if (CORE_ASPECTS.has(axis)) continue\n const explicit = explicitAxes.has(axis) && typeof member === 'string' && member.includes(':')\n const memberName = explicit ? (member as string) : null\n const typedValue = explicit\n ? null\n : member === null || member === undefined\n ? null\n : String(member)\n dimensions.push({\n axis,\n member: memberName,\n axisLabel: elements[axis]?.label ?? humanize(axis),\n memberLabel: memberName\n ? (elements[memberName]?.label ?? humanize(memberName))\n : (typedValue ?? ''),\n explicit,\n typedValue,\n })\n }\n const factSets = presentedIn.get(element) ?? []\n out.push({\n id: f.name,\n element,\n period: periodLiteral,\n unit,\n entity,\n factSet: factSets[0] ?? null,\n factSets: factSets.length ? [...factSets] : undefined,\n value,\n textValue,\n contentType: null,\n decimals,\n dimensions: dimensions.length ? dimensions : undefined,\n })\n }\n\n // ── Entity, report identity ──\n const entityName = model.entities?.[0]?.name ?? null\n const entity: EntityInfo | null = entityName\n ? {\n id: entityName,\n name: registrantName ?? humanize(entityName),\n legalName: registrantName,\n country: null,\n }\n : null\n const reportIri = namespaces.rpt ?? null\n const reportId = reportIri\n ? (reportIri.replace(/\\/$/, '').split('/').pop() ?? null)\n : (model.name ?? null)\n\n return {\n reportId,\n reportIri,\n entity,\n informationBlocks,\n structures,\n facts: out,\n elements,\n periods,\n units,\n calcAssociations,\n presAssociations,\n }\n}\n\n/** A `ReportAdapter` over an in-memory `tavi.json` document. */\nexport function taviFileAdapter(doc: string | object, source = 'tavi.json'): ReportAdapter {\n return {\n source,\n load: async () => parseTavi(doc),\n }\n}\n","/**\n * One door for both of xbrlkit's JSON projections. A holon is dataset-form\n * JSON-LD (a `@context` and named graphs); a Tavi model announces itself in\n * `documentInfo.documentType`. Callers that take \"a report file\" — a dropped\n * file, a URL — sniff here and never need to know which they were handed.\n */\nimport type { NormalizedReport } from '../model'\nimport { parseJsonld } from './jsonld'\nimport { isTaviDocument, parseTavi } from './tavi'\n\nexport type ReportFormat = 'holon' | 'tavi'\n\n/** The format of a parsed report document, or null when it is neither. */\nexport function detectReportFormat(doc: unknown): ReportFormat | null {\n if (!doc || typeof doc !== 'object') return null\n if (isTaviDocument(doc)) return 'tavi'\n const d = doc as Record<string, unknown>\n if ('@context' in d || '@graph' in d || '@id' in d) return 'holon'\n return null\n}\n\n/** Parse a report document (string or object) whichever JSON projection it is. */\nexport async function parseReportDocument(\n doc: string | object\n): Promise<{ format: ReportFormat; report: NormalizedReport }> {\n const json = (typeof doc === 'string' ? JSON.parse(doc) : doc) as object\n const format = detectReportFormat(json)\n if (format === 'tavi') return { format, report: parseTavi(json) }\n if (format === 'holon') return { format, report: await parseJsonld(json) }\n throw new Error('Not a report document: expected a holon (JSON-LD) or a Tavi compiled model')\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as AspectKey, B as BalanceType,
|
|
1
|
+
import { k as NumericKind, P as PeriodInfo, E as ElementInfo, N as NormalizedReport, I as InformationBlock, l as PivotConfig, n as PivotTable, c as SectionKind, o as PivotRow, U as UnitInfo } from './store-DlU7XE-S.js';
|
|
2
|
+
export { A as AspectKey, B as BalanceType, q as CalcAssociation, C as CypherAdapterConfig, D as DimensionQualifier, r as EntityInfo, F as Fact, s as PeriodType, t as PivotCell, u as PivotColumn, v as PivotColumnHeader, w as PivotSlicer, x as PresAssociation, R as ReportAdapter, y as ReportLabels, z as ResolvedScale, G as RowCell, H as Scale, S as SecQuery, a as SecReportShell, b as SecSection, J as Statement, K as StatementColumn, L as StatementRow, M as StructureInfo, d as cypherAdapter, f as fetchSecReportShell, e as fetchSecSection, j as jsonldFileAdapter, m as mergeSecSections, p as parseJsonld, g as parseStore, h as parseStructureDefinition, i as parseStructureName } from './store-DlU7XE-S.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import 'n3';
|
|
5
5
|
|
|
@@ -501,4 +501,4 @@ declare function jsonldFileAdapter(doc: string | object, source?: string): Repor
|
|
|
501
501
|
/** Traverse a populated quad `Store` into the normalized report model. */
|
|
502
502
|
declare function parseStore(store: Store): NormalizedReport;
|
|
503
503
|
|
|
504
|
-
export { type AspectKey as A, type BalanceType as B, type
|
|
504
|
+
export { type AspectKey as A, type BalanceType as B, type CypherAdapterConfig as C, type DimensionQualifier as D, type ElementInfo as E, type Fact as F, type RowCell as G, type Scale as H, type InformationBlock as I, type Statement as J, type StatementColumn as K, type StatementRow as L, type StructureInfo as M, type NormalizedReport as N, type PeriodInfo as P, type ReportAdapter as R, type SecQuery as S, type UnitInfo as U, type SecReportShell as a, type SecSection as b, type SectionKind as c, cypherAdapter as d, fetchSecSection as e, fetchSecReportShell as f, parseStore as g, parseStructureDefinition as h, parseStructureName as i, jsonldFileAdapter as j, type NumericKind as k, type PivotConfig as l, mergeSecSections as m, type PivotTable as n, type PivotRow as o, parseJsonld as p, type CalcAssociation as q, type EntityInfo as r, type PeriodType as s, type PivotCell as t, type PivotColumn as u, type PivotColumnHeader as v, type PivotSlicer as w, type PresAssociation as x, type ReportLabels as y, type ResolvedScale as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robosystems/report-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Source-agnostic React components for rendering XBRL-grade financial statements",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "RFS LLC",
|
|
@@ -56,15 +56,19 @@
|
|
|
56
56
|
"marked": "^18.0.6",
|
|
57
57
|
"n3": "^2.6.4"
|
|
58
58
|
},
|
|
59
|
+
"//overrides": "esbuild is forced to ^0.28.1 to clear GHSA-g7r4-m6w7-qqqr. It reaches us only through tsup, which caps at ^0.27.0 even at its latest release (8.5.1), so npm cannot resolve the fix on its own. REMOVE once tsup depends on esbuild >= 0.28.1.",
|
|
60
|
+
"overrides": {
|
|
61
|
+
"esbuild": "^0.28.1"
|
|
62
|
+
},
|
|
59
63
|
"devDependencies": {
|
|
60
|
-
"@eslint/js": "^
|
|
64
|
+
"@eslint/js": "^10.0.1",
|
|
61
65
|
"@testing-library/react": "^16.3.0",
|
|
62
66
|
"@types/jsonld": "^1.5.15",
|
|
63
67
|
"@types/n3": "^1.26.0",
|
|
64
68
|
"@types/node": "^22.0.0",
|
|
65
69
|
"@types/react": "^19.1.9",
|
|
66
70
|
"@types/react-dom": "^19.1.9",
|
|
67
|
-
"eslint": "^9.
|
|
71
|
+
"eslint": "^10.9.1",
|
|
68
72
|
"eslint-config-prettier": "^10.0.0",
|
|
69
73
|
"eslint-plugin-prettier": "^5.0.0",
|
|
70
74
|
"happy-dom": "^20.0.8",
|