ixbrl-viewer 1.4.1__py3-none-any.whl → 1.4.86__py3-none-any.whl
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.
- iXBRLViewerPlugin/__init__.py +231 -127
- iXBRLViewerPlugin/_version.py +33 -3
- iXBRLViewerPlugin/constants.py +96 -2
- iXBRLViewerPlugin/featureConfig.py +8 -1
- iXBRLViewerPlugin/iXBRLViewer.py +356 -214
- iXBRLViewerPlugin/plugin.py +12 -0
- iXBRLViewerPlugin/ui.py +81 -50
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js +1 -1
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js.LICENSE.txt +12 -5
- iXBRLViewerPlugin/viewer/i18next-parser.config.js +1 -1
- iXBRLViewerPlugin/viewer/src/data/utr.json +1244 -0
- iXBRLViewerPlugin/viewer/src/html/fact-details.html +69 -38
- iXBRLViewerPlugin/viewer/src/html/footer-logo.html +4 -0
- iXBRLViewerPlugin/viewer/src/html/footnote-details.html +2 -2
- iXBRLViewerPlugin/viewer/src/html/inspector.html +352 -197
- iXBRLViewerPlugin/viewer/src/i18n/cy/balancetypes.json +1 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/datatypes.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/labelroles.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/translation.json +73 -23
- iXBRLViewerPlugin/viewer/src/i18n/es/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/datatypes.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/translation.json +87 -37
- iXBRLViewerPlugin/viewer/src/i18n/fr/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/icons/calculator.svg +13 -0
- iXBRLViewerPlugin/viewer/src/icons/circle-cross.svg +11 -0
- iXBRLViewerPlugin/viewer/src/icons/circle-tick.svg +11 -0
- iXBRLViewerPlugin/viewer/src/icons/dark-mode.svg +4 -0
- iXBRLViewerPlugin/viewer/src/icons/dimension.svg +1 -5
- iXBRLViewerPlugin/viewer/src/icons/member.svg +2 -5
- iXBRLViewerPlugin/viewer/src/icons/multi-tag.svg +10 -0
- iXBRLViewerPlugin/viewer/src/img/arelle-dark.svg +179 -0
- iXBRLViewerPlugin/viewer/src/img/inline-viewer-dark.svg +59 -0
- iXBRLViewerPlugin/viewer/src/js/accordian.js +5 -4
- iXBRLViewerPlugin/viewer/src/js/aspect.js +29 -10
- iXBRLViewerPlugin/viewer/src/js/aspect.test.js +40 -31
- iXBRLViewerPlugin/viewer/src/js/balance.js +14 -0
- iXBRLViewerPlugin/viewer/src/js/calculation.js +213 -0
- iXBRLViewerPlugin/viewer/src/js/calculation.test.js +306 -0
- iXBRLViewerPlugin/viewer/src/js/calculationInspector.js +187 -0
- iXBRLViewerPlugin/viewer/src/js/chart.js +26 -24
- iXBRLViewerPlugin/viewer/src/js/chart.test.js +10 -9
- iXBRLViewerPlugin/viewer/src/js/concept.js +37 -4
- iXBRLViewerPlugin/viewer/src/js/concept.test.js +30 -6
- iXBRLViewerPlugin/viewer/src/js/datatype.js +20 -0
- iXBRLViewerPlugin/viewer/src/js/datatype.test.js +62 -0
- iXBRLViewerPlugin/viewer/src/js/dialog.js +6 -4
- iXBRLViewerPlugin/viewer/src/js/docOrderIndex.js +7 -7
- iXBRLViewerPlugin/viewer/src/js/fact.js +156 -59
- iXBRLViewerPlugin/viewer/src/js/fact.test.js +160 -29
- iXBRLViewerPlugin/viewer/src/js/factset.js +64 -15
- iXBRLViewerPlugin/viewer/src/js/factset.test.js +102 -31
- iXBRLViewerPlugin/viewer/src/js/footnote.js +8 -2
- iXBRLViewerPlugin/viewer/src/js/index.js +11 -3
- iXBRLViewerPlugin/viewer/src/js/inspector.js +747 -221
- iXBRLViewerPlugin/viewer/src/js/inspector.test.js +143 -25
- iXBRLViewerPlugin/viewer/src/js/interval.js +70 -0
- iXBRLViewerPlugin/viewer/src/js/interval.test.js +153 -0
- iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.js +391 -262
- iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.test.js +134 -20
- iXBRLViewerPlugin/viewer/src/js/ixnode.js +1 -1
- iXBRLViewerPlugin/viewer/src/js/menu.js +25 -7
- iXBRLViewerPlugin/viewer/src/js/number-matcher.js +7 -3
- iXBRLViewerPlugin/viewer/src/js/number-matcher.test.js +4 -0
- iXBRLViewerPlugin/viewer/src/js/outline.js +34 -13
- iXBRLViewerPlugin/viewer/src/js/outline.test.js +97 -91
- iXBRLViewerPlugin/viewer/src/js/period.js +0 -1
- iXBRLViewerPlugin/viewer/src/js/report.js +260 -351
- iXBRLViewerPlugin/viewer/src/js/report.test.js +95 -27
- iXBRLViewerPlugin/viewer/src/js/reportset.js +264 -0
- iXBRLViewerPlugin/viewer/src/js/reportset.test.js +357 -0
- iXBRLViewerPlugin/viewer/src/js/search.js +72 -38
- iXBRLViewerPlugin/viewer/src/js/search.test.js +184 -84
- iXBRLViewerPlugin/viewer/src/js/summary.js +34 -8
- iXBRLViewerPlugin/viewer/src/js/summary.test.js +69 -25
- iXBRLViewerPlugin/viewer/src/js/tableExport.js +9 -9
- iXBRLViewerPlugin/viewer/src/js/taxonomynamer.js +34 -0
- iXBRLViewerPlugin/viewer/src/js/taxonomynamer.test.js +32 -0
- iXBRLViewerPlugin/viewer/src/js/test-utils.js +46 -0
- iXBRLViewerPlugin/viewer/src/js/theme.js +50 -0
- iXBRLViewerPlugin/viewer/src/js/unit.js +90 -32
- iXBRLViewerPlugin/viewer/src/js/unit.test.js +62 -25
- iXBRLViewerPlugin/viewer/src/js/util.js +94 -0
- iXBRLViewerPlugin/viewer/src/js/util.test.js +33 -1
- iXBRLViewerPlugin/viewer/src/js/utr.js +27 -0
- iXBRLViewerPlugin/viewer/src/js/viewer.js +205 -181
- iXBRLViewerPlugin/viewer/src/js/viewerOptions.js +0 -2
- iXBRLViewerPlugin/viewer/src/less/accordian.less +10 -6
- iXBRLViewerPlugin/viewer/src/less/block-list.less +16 -5
- iXBRLViewerPlugin/viewer/src/less/calculation-inspector.less +83 -0
- iXBRLViewerPlugin/viewer/src/less/chart.less +8 -5
- iXBRLViewerPlugin/viewer/src/less/colours-dark-mode.less +40 -0
- iXBRLViewerPlugin/viewer/src/less/colours.less +32 -20
- iXBRLViewerPlugin/viewer/src/less/common.less +3 -3
- iXBRLViewerPlugin/viewer/src/less/components.less +6 -4
- iXBRLViewerPlugin/viewer/src/less/core.less +2 -0
- iXBRLViewerPlugin/viewer/src/less/dialog.less +21 -14
- iXBRLViewerPlugin/viewer/src/less/form-controls.less +33 -11
- iXBRLViewerPlugin/viewer/src/less/inspector.less +1045 -726
- iXBRLViewerPlugin/viewer/src/less/loader.less +2 -2
- iXBRLViewerPlugin/viewer/src/less/menu.less +33 -15
- iXBRLViewerPlugin/viewer/src/less/summary.less +16 -6
- iXBRLViewerPlugin/viewer/src/less/tabs.less +9 -9
- iXBRLViewerPlugin/viewer/src/less/text-block-viewer.less +2 -0
- iXBRLViewerPlugin/viewer/src/less/text-mixins.less +2 -1
- iXBRLViewerPlugin/viewer/src/less/validation-report.less +2 -3
- iXBRLViewerPlugin/viewer/src/less/viewer.less +105 -74
- iXBRLViewerPlugin/viewer/webpack.common.js +19 -9
- iXBRLViewerPlugin/xhtmlserialize.py +59 -45
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/METADATA +181 -50
- ixbrl_viewer-1.4.86.dist-info/RECORD +217 -0
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/WHEEL +1 -1
- ixbrl_viewer-1.4.1.dist-info/LICENSE → ixbrl_viewer-1.4.86.dist-info/licenses/LICENSE.md +8 -14
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/top_level.txt +0 -1
- iXBRLViewerPlugin/viewer/src/js/calculations.js +0 -111
- iXBRLViewerPlugin/viewer/src/js/interact.min.js +0 -6
- ixbrl_viewer-1.4.1.dist-info/RECORD +0 -155
- tests/__init__.py +0 -0
- tests/puppeteer/framework/core_elements.js +0 -117
- tests/puppeteer/framework/page_objects/doc_frame.js +0 -105
- tests/puppeteer/framework/page_objects/fact_details_panel.js +0 -80
- tests/puppeteer/framework/page_objects/search_panel.js +0 -76
- tests/puppeteer/framework/page_objects/toolbar.js +0 -18
- tests/puppeteer/framework/utils.js +0 -3
- tests/puppeteer/framework/viewer_page.js +0 -103
- tests/puppeteer/puppeteer_test_run_via_intellij.jpg +0 -0
- tests/puppeteer/test_filings/filing_documents_smoke_test.zip +0 -0
- tests/puppeteer/test_filings/highlights.zip +0 -0
- tests/puppeteer/tests/fact_properties.test.js +0 -78
- tests/puppeteer/tests/highlight.test.js +0 -186
- tests/puppeteer/tests/search.test.js +0 -86
- tests/puppeteer/tools/generate.sh +0 -15
- tests/unit_tests/__init__.py +0 -0
- tests/unit_tests/iXBRLViewerPlugin/__init__.py +0 -0
- tests/unit_tests/iXBRLViewerPlugin/mock_arelle.py +0 -39
- tests/unit_tests/iXBRLViewerPlugin/test_iXBRLViewer.py +0 -641
- tests/unit_tests/iXBRLViewerPlugin/test_xhtmlserialize.py +0 -310
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/entry_points.txt +0 -0
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info/licenses}/NOTICE +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// See COPYRIGHT.md for copyright information
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ReportSet } from "./reportset.js";
|
|
4
4
|
import { ViewerOptions } from "./viewerOptions.js";
|
|
5
|
+
import { TestInspector } from "./test-utils.js";
|
|
6
|
+
import { NAMESPACE_ISO4217 } from "./util";
|
|
5
7
|
|
|
6
8
|
var testReportData = {
|
|
7
9
|
"languages": {
|
|
@@ -10,13 +12,17 @@ var testReportData = {
|
|
|
10
12
|
},
|
|
11
13
|
"prefixes": {
|
|
12
14
|
"eg": "http://www.example.com",
|
|
13
|
-
"iso4217":
|
|
15
|
+
"iso4217": NAMESPACE_ISO4217
|
|
14
16
|
},
|
|
15
17
|
"roles": {
|
|
16
18
|
"role1": "https://www.example.com/role1",
|
|
17
19
|
"role2": "https://www.example.com/role2",
|
|
18
20
|
"role3": "https://www.example.com/role3",
|
|
19
|
-
"role4": "https://www.example.com/
|
|
21
|
+
"role4": "https://www.example.com/role4MoreWords",
|
|
22
|
+
"std": "http://www.xbrl.org/2003/role/label",
|
|
23
|
+
"doc": "http://www.xbrl.org/2003/role/documentation",
|
|
24
|
+
"verbose": "http://www.xbrl.org/2003/role/verboseLabel",
|
|
25
|
+
"total": "http://www.xbrl.org/2003/role/totalLabel",
|
|
20
26
|
},
|
|
21
27
|
"roleDefs": {
|
|
22
28
|
"role1": { "en": "Role 1 Label" },
|
|
@@ -61,68 +67,78 @@ var testReportData = {
|
|
|
61
67
|
"p": "2018-01-01/2019-01-01",
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
|
-
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
"softwareCredits": ["Example credit text A", "Example credit text B"],
|
|
65
73
|
};
|
|
66
74
|
|
|
75
|
+
var insp = new TestInspector();
|
|
76
|
+
beforeAll(() => {
|
|
77
|
+
return insp.i18nInit();
|
|
78
|
+
});
|
|
67
79
|
|
|
68
80
|
describe("Language options", () => {
|
|
69
|
-
|
|
70
|
-
|
|
81
|
+
const testReportSet = new ReportSet(testReportData);
|
|
82
|
+
testReportSet._initialize();
|
|
71
83
|
test("Available languages", () => {
|
|
72
|
-
|
|
84
|
+
const al = testReportSet.availableLanguages();
|
|
73
85
|
expect(al).toHaveLength(6);
|
|
74
86
|
expect(al).toEqual(expect.arrayContaining(["en", "en-us", "en-gb", "fr", "de", "es"]));
|
|
75
87
|
});
|
|
76
|
-
|
|
77
|
-
test("Names for available languages", () => {
|
|
78
|
-
var ln = testReport.languageNames();
|
|
79
|
-
expect(Object.keys(ln)).toHaveLength(2);
|
|
80
|
-
expect(ln['en']).toBe("English");
|
|
81
|
-
expect(ln['en-us']).toBe("English (US)");
|
|
82
|
-
});
|
|
83
88
|
});
|
|
84
89
|
|
|
85
90
|
describe("Fetching facts", () => {
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
const testReportSet = new ReportSet(testReportData);
|
|
92
|
+
testReportSet._initialize();
|
|
88
93
|
|
|
89
94
|
test("Successful", () => {
|
|
90
|
-
|
|
91
|
-
testReport._initialize();
|
|
95
|
+
const f = testReportSet.getItemById("0-f1");
|
|
92
96
|
expect(f).not.toBeNull();
|
|
93
97
|
expect(f.decimals()).toEqual(-3);
|
|
94
98
|
});
|
|
95
99
|
|
|
96
100
|
test("Non-existent fact", () => {
|
|
97
|
-
|
|
101
|
+
const f = testReportSet.getItemById("fact-does-not-exist");
|
|
98
102
|
expect(f).toBeUndefined();
|
|
99
103
|
});
|
|
100
104
|
});
|
|
101
105
|
|
|
102
106
|
describe("Concept labels", () => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
testReport.
|
|
107
|
+
const testReportSet = new ReportSet(testReportData);
|
|
108
|
+
testReportSet._initialize();
|
|
109
|
+
const testReport = testReportSet.reports[0];
|
|
110
|
+
const vo = new ViewerOptions();
|
|
111
|
+
testReportSet.viewerOptions = vo;
|
|
106
112
|
test("Label fallback", () => {
|
|
107
113
|
vo.language = 'fr';
|
|
108
114
|
expect(testReport.getLabel('eg:Concept3', 'std')).toBe("Concept trois");
|
|
115
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std').label).toBe("Concept trois");
|
|
116
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std').lang).toBe("fr");
|
|
109
117
|
expect(testReport.getLabelOrName('eg:Concept3', 'std')).toBe("Concept trois");
|
|
110
118
|
vo.language = 'es';
|
|
111
119
|
expect(testReport.getLabel('eg:Concept3', 'std')).toBe("Concept cuatro");
|
|
120
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std').label).toBe("Concept cuatro");
|
|
121
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std').lang).toBe("es");
|
|
112
122
|
expect(testReport.getLabelOrName('eg:Concept3', 'std')).toBe("Concept cuatro");
|
|
113
123
|
// No English label, so fall back on German (de is first alphabetically)
|
|
114
124
|
vo.language = 'en';
|
|
115
125
|
expect(testReport.getLabel('eg:Concept3', 'std')).toBe("Concept vier");
|
|
126
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std').label).toBe("Concept vier");
|
|
127
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std').lang).toBe("de");
|
|
116
128
|
expect(testReport.getLabelOrName('eg:Concept3', 'std')).toBe("Concept vier");
|
|
117
129
|
|
|
118
130
|
// Attempt to get an undefined label type
|
|
119
131
|
expect(testReport.getLabel('eg:Concept3', 'doc')).toBeUndefined();
|
|
132
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'doc').label).toBeUndefined();
|
|
133
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'doc').lang).toBeUndefined();
|
|
120
134
|
expect(testReport.getLabelOrName('eg:Concept3', 'doc')).toBe('eg:Concept3');
|
|
121
135
|
});
|
|
122
136
|
|
|
123
137
|
test("With prefix", () => {
|
|
124
138
|
vo.language = 'fr';
|
|
125
139
|
expect(testReport.getLabel('eg:Concept3', 'std', true)).toBe("(eg) Concept trois");
|
|
140
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std', true).label).toBe("(eg) Concept trois");
|
|
141
|
+
expect(testReport.getLabelAndLang('eg:Concept3', 'std', true).lang).toBe("fr");
|
|
126
142
|
expect(testReport.getLabelOrName('eg:Concept3', 'std', true)).toBe("(eg) Concept trois");
|
|
127
143
|
|
|
128
144
|
expect(testReport.getLabel('eg:Concept3', 'doc', true)).toBeUndefined();
|
|
@@ -132,18 +148,70 @@ describe("Concept labels", () => {
|
|
|
132
148
|
});
|
|
133
149
|
|
|
134
150
|
describe("ELR labels", () => {
|
|
135
|
-
const
|
|
151
|
+
const testReportSet = new ReportSet(testReportData);
|
|
152
|
+
testReportSet._initialize();
|
|
153
|
+
const testReport = testReportSet.reports[0];
|
|
136
154
|
test("Present", () => {
|
|
137
|
-
expect(testReport.
|
|
155
|
+
expect(testReport.getRoleLabelOrURI("role1")).toBe("Role 1 Label");
|
|
138
156
|
});
|
|
139
157
|
test("Null", () => {
|
|
140
|
-
expect(testReport.
|
|
158
|
+
expect(testReport.getRoleLabelOrURI("role2")).toBe("https://www.example.com/role2");
|
|
141
159
|
});
|
|
142
160
|
test("No label", () => {
|
|
143
|
-
expect(testReport.
|
|
161
|
+
expect(testReport.getRoleLabelOrURI("role3")).toBe("https://www.example.com/role3");
|
|
144
162
|
});
|
|
145
163
|
test("Not present in roleDef", () => {
|
|
146
|
-
expect(testReport.
|
|
164
|
+
expect(testReport.getRoleLabelOrURI("role4")).toBe("https://www.example.com/role4MoreWords");
|
|
147
165
|
});
|
|
166
|
+
});
|
|
148
167
|
|
|
168
|
+
describe("Label role labels", () => {
|
|
169
|
+
const testReportSet = new ReportSet(testReportData);
|
|
170
|
+
testReportSet._initialize();
|
|
171
|
+
const testReport = testReportSet.reports[0];
|
|
172
|
+
test("Built-in (via i18n)", () => {
|
|
173
|
+
expect(testReport.getLabelRoleLabel("std")).toBe("Standard Label");
|
|
174
|
+
});
|
|
175
|
+
test("Built-in (via i18n)", () => {
|
|
176
|
+
expect(testReport.getLabelRoleLabel("doc")).toBe("Documentation Label");
|
|
177
|
+
});
|
|
178
|
+
test("Built-in (via de-camelcase)", () => {
|
|
179
|
+
expect(testReport.getLabelRoleLabel("verbose")).toBe("Verbose Label");
|
|
180
|
+
});
|
|
181
|
+
test("Present", () => {
|
|
182
|
+
expect(testReport.getLabelRoleLabel("role1")).toBe("Role 1 Label");
|
|
183
|
+
});
|
|
184
|
+
test("Null", () => {
|
|
185
|
+
expect(testReport.getLabelRoleLabel("role2")).toBe("Role2");
|
|
186
|
+
});
|
|
187
|
+
test("No label", () => {
|
|
188
|
+
expect(testReport.getLabelRoleLabel("role3")).toBe("Role3");
|
|
189
|
+
});
|
|
190
|
+
test("Not present in roleDef", () => {
|
|
191
|
+
expect(testReport.getLabelRoleLabel("role4")).toBe("Role4 More Words");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe("Fetching software credit", () => {
|
|
197
|
+
|
|
198
|
+
test("Successful", () => {
|
|
199
|
+
const testReportSet = new ReportSet(testReportData);
|
|
200
|
+
testReportSet._initialize();
|
|
201
|
+
const report = testReportSet.reports[0];
|
|
202
|
+
|
|
203
|
+
const softwareCredits = report.softwareCredits();
|
|
204
|
+
expect(softwareCredits).toEqual(["Example credit text A", "Example credit text B"]);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("Unset", () => {
|
|
208
|
+
let alternateData = JSON.parse(JSON.stringify(testReportData));
|
|
209
|
+
delete alternateData.softwareCredits;
|
|
210
|
+
const testReportSet = new ReportSet(alternateData);
|
|
211
|
+
testReportSet._initialize();
|
|
212
|
+
const report = testReportSet.reports[0];
|
|
213
|
+
|
|
214
|
+
const softwareCredits = report.softwareCredits();
|
|
215
|
+
expect(softwareCredits).toEqual([]);
|
|
216
|
+
});
|
|
149
217
|
});
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// See COPYRIGHT.md for copyright information
|
|
2
|
+
|
|
3
|
+
import { XBRLReport } from './report.js';
|
|
4
|
+
import { Fact } from "./fact.js"
|
|
5
|
+
import { Footnote } from "./footnote.js"
|
|
6
|
+
import { Unit } from "./unit";
|
|
7
|
+
import { titleCase, viewerUniqueId } from "./util.js";
|
|
8
|
+
import { QName } from "./qname.js";
|
|
9
|
+
import { ViewerOptions } from './viewerOptions.js';
|
|
10
|
+
import { TaxonomyNamer } from './taxonomynamer.js';
|
|
11
|
+
|
|
12
|
+
// Class represents the set of XBRL "target" reports shown in the viewer.
|
|
13
|
+
// Each contained report represents the data from a single target document in a
|
|
14
|
+
// single iXBRL Document or iXBRL Document Set
|
|
15
|
+
|
|
16
|
+
export class ReportSet {
|
|
17
|
+
constructor(data) {
|
|
18
|
+
this._data = data;
|
|
19
|
+
this._ixNodeMap = {};
|
|
20
|
+
this.viewerOptions = new ViewerOptions()
|
|
21
|
+
this.taxonomyNamer = new TaxonomyNamer(new Map());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Set additional information about facts obtained from parsing the iXBRL.
|
|
26
|
+
*/
|
|
27
|
+
setIXNodeMap(ixData) {
|
|
28
|
+
this._ixNodeMap = ixData;
|
|
29
|
+
this._initialize();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_initialize() {
|
|
33
|
+
this._items = {};
|
|
34
|
+
this.reports = [];
|
|
35
|
+
// Build an array of footnotes IDs in document order so that we can assign
|
|
36
|
+
// numbers to foonotes
|
|
37
|
+
const fnorder = Object.keys(this._ixNodeMap).filter((id) => this._ixNodeMap[id].footnote);
|
|
38
|
+
fnorder.sort((a,b) => this._ixNodeMap[a].docOrderindex - this._ixNodeMap[b].docOrderindex);
|
|
39
|
+
|
|
40
|
+
// Create Fact objects for all facts.
|
|
41
|
+
for (const [reportIndex, sourceReport] of (this._data.sourceReports ?? [ { "targetReports": [ this._data ] } ]).entries()) {
|
|
42
|
+
for (const reportData of sourceReport.targetReports) {
|
|
43
|
+
const report = new XBRLReport(this, reportData);
|
|
44
|
+
this.reports.push(report);
|
|
45
|
+
for (const [id, factData] of Object.entries(reportData.facts)) {
|
|
46
|
+
const vuid = viewerUniqueId(reportIndex, id);
|
|
47
|
+
this._items[vuid] = new Fact(report, vuid, factData);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Now resolve footnote references, creating footnote objects for "normal"
|
|
51
|
+
// footnotes, and finding Fact objects for fact->fact footnotes.
|
|
52
|
+
//
|
|
53
|
+
// Associate source facts with target footnote/facts to allow two way
|
|
54
|
+
// navigation.
|
|
55
|
+
for (const [id, factData] of Object.entries(reportData.facts)) {
|
|
56
|
+
const vuid = viewerUniqueId(reportIndex, id);
|
|
57
|
+
const fact = this._items[vuid];
|
|
58
|
+
const fns = factData.fn || [];
|
|
59
|
+
fns.forEach((fnid) => {
|
|
60
|
+
const fnvuid = viewerUniqueId(reportIndex, fnid);
|
|
61
|
+
var fn = this._items[fnvuid];
|
|
62
|
+
if (fn === undefined) {
|
|
63
|
+
fn = new Footnote(fact.report, fnvuid, "Footnote " + (fnorder.indexOf(fnvuid) + 1));
|
|
64
|
+
this._items[fnvuid] = fn;
|
|
65
|
+
}
|
|
66
|
+
// Associate fact with footnote
|
|
67
|
+
fn.addLinkedFact(fact);
|
|
68
|
+
fact.addFootnote(fn);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
availableLanguages() {
|
|
76
|
+
return Array.from(this.reports.reduce(
|
|
77
|
+
(langs, report) => new Set([...langs, ...report.availableLanguages()]),
|
|
78
|
+
new Set()
|
|
79
|
+
));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getItemById(vuid) {
|
|
83
|
+
return this._items[vuid];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getIXNodeForItemId(vuid) {
|
|
87
|
+
return this._ixNodeMap[vuid] || {};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
facts() {
|
|
91
|
+
return Object.values(this._items).filter(i => i instanceof Fact);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
filingDocuments() {
|
|
95
|
+
return this._data.filingDocuments;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
prefixMap() {
|
|
99
|
+
return this._data.prefixes;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
preferredPrefix(prefix) {
|
|
103
|
+
return this.taxonomyNamer.getName(prefix, this._data.prefixes[prefix]).prefix;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
namespaceGroups() {
|
|
107
|
+
const counts = {};
|
|
108
|
+
for (const f of this.facts()) {
|
|
109
|
+
counts[f.conceptQName().prefix] = (counts[f.conceptQName().prefix] || 0) + 1;
|
|
110
|
+
}
|
|
111
|
+
const prefixes = Object.keys(counts);
|
|
112
|
+
prefixes.sort((a, b) => counts[b] - counts[a]);
|
|
113
|
+
return prefixes;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getUsedConceptPrefixes() {
|
|
117
|
+
if (this._usedPrefixes === undefined) {
|
|
118
|
+
this._usedPrefixes = new Set(Object.values(this._items)
|
|
119
|
+
.filter(f => f instanceof Fact)
|
|
120
|
+
.map(f => f.getConceptPrefix()));
|
|
121
|
+
}
|
|
122
|
+
return this._usedPrefixes;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
getUsedConceptDataTypes() {
|
|
126
|
+
if (this._usedDataTypes === undefined) {
|
|
127
|
+
const map = new Map()
|
|
128
|
+
for (const dt of Object.values(this._items)
|
|
129
|
+
.filter(f => f instanceof Fact)
|
|
130
|
+
.map(f => ({ dataType: f.concept().dataType(), isNumeric: f.isNumeric() }))
|
|
131
|
+
.filter(t => t.dataType !== undefined)) {
|
|
132
|
+
map.set(dt.dataType.name, dt);
|
|
133
|
+
}
|
|
134
|
+
this._usedDataTypes = map.values().toArray();
|
|
135
|
+
}
|
|
136
|
+
return this._usedDataTypes;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @return {Array[String]} Sorted list of unique software credit text values
|
|
141
|
+
*/
|
|
142
|
+
getSoftwareCredits() {
|
|
143
|
+
let softwareCredits = new Set(this.reports.flatMap(r => r.softwareCredits()));
|
|
144
|
+
return Array.from(softwareCredits).sort();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
getTargetDocuments() {
|
|
148
|
+
if (this._targetDocuments === undefined) {
|
|
149
|
+
this._targetDocuments = new Set(Object.values(this._items)
|
|
150
|
+
.filter(f => f instanceof Fact)
|
|
151
|
+
.map(f => f.targetDocument()));
|
|
152
|
+
}
|
|
153
|
+
return this._targetDocuments;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Returns a set of OIM format unit strings used by facts on this report. Lazy-loaded.
|
|
158
|
+
* @return {Set[String]} Set of OIM format unit strings
|
|
159
|
+
*/
|
|
160
|
+
getUsedUnits() {
|
|
161
|
+
if (this._usedUnits === undefined) {
|
|
162
|
+
this._usedUnits = new Set(Object.values(this._items)
|
|
163
|
+
.filter(f => f instanceof Fact)
|
|
164
|
+
.map(f => f.unit()?.value())
|
|
165
|
+
.filter(f => f)
|
|
166
|
+
.sort());
|
|
167
|
+
}
|
|
168
|
+
return this._usedUnits;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Returns details about the provided unit. Lazy-loaded once per unit.
|
|
173
|
+
* @param {String} unitKey Unit in OIM format
|
|
174
|
+
* @return {Unit} Unit instance corresponding with provided key
|
|
175
|
+
*/
|
|
176
|
+
getUnit(unitKey) {
|
|
177
|
+
if (this._unitsMap === undefined) {
|
|
178
|
+
this._unitsMap = {};
|
|
179
|
+
}
|
|
180
|
+
if (this._unitsMap[unitKey] === undefined) {
|
|
181
|
+
this._unitsMap[unitKey] = new Unit(this, unitKey)
|
|
182
|
+
}
|
|
183
|
+
return this._unitsMap[unitKey];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
getUsedScalesMap() {
|
|
187
|
+
// Do not lazy load. This is language-dependent so needs to re-evaluate after language changes.
|
|
188
|
+
const usedScalesMap = {};
|
|
189
|
+
Object.values(this._items)
|
|
190
|
+
.filter(f => f instanceof Fact)
|
|
191
|
+
.forEach(fact => {
|
|
192
|
+
const scale = fact.scale();
|
|
193
|
+
if (scale !== null && scale !== undefined) {
|
|
194
|
+
if (!(scale in usedScalesMap)) {
|
|
195
|
+
usedScalesMap[scale] = new Set();
|
|
196
|
+
}
|
|
197
|
+
const labels = usedScalesMap[scale];
|
|
198
|
+
const label = titleCase(fact.getScaleLabel(scale));
|
|
199
|
+
if (label && !labels.has(label)) {
|
|
200
|
+
labels.add(label);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
return usedScalesMap;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
roleMap() {
|
|
208
|
+
return this._data.roles;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
qname(v) {
|
|
212
|
+
return new QName(this.prefixMap(), v);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
reportsData() {
|
|
216
|
+
return this._data.sourceReports?.flatMap(sr => sr.targetReports) ?? [ this._data ];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Returns a flat list of source files for all reports in the report set.
|
|
221
|
+
* Each entry in the list is an object with:
|
|
222
|
+
* file - name of the file
|
|
223
|
+
* index - index of the report that it is for
|
|
224
|
+
* May return an empty list for single file, non-stub viewers.
|
|
225
|
+
* @return {List} A list of objects describing each file
|
|
226
|
+
*/
|
|
227
|
+
reportFiles() {
|
|
228
|
+
const sourceReports = this._data.sourceReports ?? [ this._data ];
|
|
229
|
+
return sourceReports.map((x, n) => (x.docSetFiles ?? []).map(file => ({ index: n, file: file }))).flat();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Returns true if the viewer is for more than one Inline XBRL document
|
|
234
|
+
* This may be a single document set with multiple files, or multiple
|
|
235
|
+
* document sets
|
|
236
|
+
* @return {Boolean} true if the viewer covers more than one iXBRL
|
|
237
|
+
* document
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
isMultiDocumentViewer() {
|
|
241
|
+
return this.reportFiles().length > 1;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
usesAnchoring() {
|
|
245
|
+
return this.reportsData().some(r => r.rels?.["w-n"] !== undefined);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
usesCalculations() {
|
|
249
|
+
return this.reportsData().some(r => Object.keys(r.rels?.calc ?? {}).length > 0);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
hasValidationErrors() {
|
|
253
|
+
return this._data.validation !== undefined && this._data.validation.length > 0;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
validation() {
|
|
257
|
+
return this._data.validation;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
factsForReport(report) {
|
|
261
|
+
return Object.values(this._items).filter(i => i instanceof Fact && i.report == report);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
}
|