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
|
@@ -6,7 +6,8 @@ import { DocumentSummary } from "./summary.js";
|
|
|
6
6
|
function testConcept(typedDomainElement) {
|
|
7
7
|
return {
|
|
8
8
|
isTypedDimension: () => typedDomainElement !== undefined,
|
|
9
|
-
typedDomainElement: () => typedDomainElement
|
|
9
|
+
typedDomainElement: () => typedDomainElement,
|
|
10
|
+
hasDefinition: true,
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -17,19 +18,26 @@ function testFact(conceptName, dimensions) {
|
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
function
|
|
21
|
-
|
|
21
|
+
function testReportSet(concepts, facts, documents, softwareCredits) {
|
|
22
|
+
const report = {
|
|
22
23
|
getConcept: conceptName => concepts[conceptName],
|
|
24
|
+
localDocuments: () => documents,
|
|
25
|
+
}
|
|
26
|
+
for (const f of facts) {
|
|
27
|
+
f.report = report;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
23
30
|
facts: () => facts,
|
|
24
|
-
|
|
31
|
+
getSoftwareCredits: () => softwareCredits,
|
|
32
|
+
reports: [ report ]
|
|
25
33
|
}
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
describe("Facts summary", () => {
|
|
29
37
|
|
|
30
38
|
test("no facts", () => {
|
|
31
|
-
const
|
|
32
|
-
const summary = new DocumentSummary(
|
|
39
|
+
const reportSet = testReportSet({}, [], {}, []);
|
|
40
|
+
const summary = new DocumentSummary(reportSet);
|
|
33
41
|
|
|
34
42
|
expect(summary.totalFacts()).toBe(0);
|
|
35
43
|
});
|
|
@@ -37,10 +45,10 @@ describe("Facts summary", () => {
|
|
|
37
45
|
test("multiple facts", () => {
|
|
38
46
|
const facts = [];
|
|
39
47
|
for (let i = 0; i < 10; i++) {
|
|
40
|
-
facts.push(testFact("eg:Concept1", {}));
|
|
48
|
+
facts.push(testFact("eg:Concept1", {}, []));
|
|
41
49
|
}
|
|
42
|
-
const
|
|
43
|
-
const summary = new DocumentSummary(
|
|
50
|
+
const reportSet = testReportSet({}, facts, {}, []);
|
|
51
|
+
const summary = new DocumentSummary(reportSet);
|
|
44
52
|
|
|
45
53
|
expect(summary.totalFacts()).toBe(10);
|
|
46
54
|
});
|
|
@@ -49,8 +57,8 @@ describe("Facts summary", () => {
|
|
|
49
57
|
const conceptName = "eg:Concept1";
|
|
50
58
|
const fact1 = testFact(conceptName, {});
|
|
51
59
|
const fact2 = testFact(conceptName, {});
|
|
52
|
-
const
|
|
53
|
-
const summary = new DocumentSummary(
|
|
60
|
+
const reportSet = testReportSet({}, [fact1, fact2], {}, []);
|
|
61
|
+
const summary = new DocumentSummary(reportSet);
|
|
54
62
|
|
|
55
63
|
expect(summary.totalFacts()).toBe(2);
|
|
56
64
|
});
|
|
@@ -60,8 +68,8 @@ describe("Facts summary", () => {
|
|
|
60
68
|
describe("Tags summary", () => {
|
|
61
69
|
|
|
62
70
|
test("no tags", () => {
|
|
63
|
-
const
|
|
64
|
-
const summary = new DocumentSummary(
|
|
71
|
+
const reportSet = testReportSet({}, [], {}, [])
|
|
72
|
+
const summary = new DocumentSummary(reportSet);
|
|
65
73
|
|
|
66
74
|
expect(summary.tagCounts()).toEqual(new Map());
|
|
67
75
|
});
|
|
@@ -70,8 +78,8 @@ describe("Tags summary", () => {
|
|
|
70
78
|
const fact1 = testFact("eg:Concept1", {});
|
|
71
79
|
const fact2 = testFact("eg:Concept2", {});
|
|
72
80
|
const fact3 = testFact("xz:Concept1", {});
|
|
73
|
-
const
|
|
74
|
-
const summary = new DocumentSummary(
|
|
81
|
+
const reportSet = testReportSet({}, [fact1, fact2, fact3], {}, [])
|
|
82
|
+
const summary = new DocumentSummary(reportSet);
|
|
75
83
|
|
|
76
84
|
expect(Object.fromEntries(summary.tagCounts())).toEqual({
|
|
77
85
|
'eg': {
|
|
@@ -99,8 +107,8 @@ describe("Tags summary", () => {
|
|
|
99
107
|
const concepts = {
|
|
100
108
|
[dimension]: testConcept(),
|
|
101
109
|
}
|
|
102
|
-
const
|
|
103
|
-
const summary = new DocumentSummary(
|
|
110
|
+
const reportSet = testReportSet(concepts, [fact], {}, [])
|
|
111
|
+
const summary = new DocumentSummary(reportSet);
|
|
104
112
|
|
|
105
113
|
expect(Object.fromEntries(summary.tagCounts())).toEqual({
|
|
106
114
|
'eg': {
|
|
@@ -129,8 +137,8 @@ describe("Tags summary", () => {
|
|
|
129
137
|
[dimension2]: testConcept(),
|
|
130
138
|
[dimension3]: testConcept(),
|
|
131
139
|
}
|
|
132
|
-
const
|
|
133
|
-
const summary = new DocumentSummary(
|
|
140
|
+
const reportSet = testReportSet(concepts, [fact], {}, [])
|
|
141
|
+
const summary = new DocumentSummary(reportSet);
|
|
134
142
|
|
|
135
143
|
expect(Object.fromEntries(summary.tagCounts())).toEqual({
|
|
136
144
|
'ab': {
|
|
@@ -170,8 +178,8 @@ describe("Tags summary", () => {
|
|
|
170
178
|
const concepts = {
|
|
171
179
|
[dimension]: testConcept(typedDomain),
|
|
172
180
|
}
|
|
173
|
-
const
|
|
174
|
-
const summary = new DocumentSummary(
|
|
181
|
+
const reportSet = testReportSet(concepts, [fact], {}, [])
|
|
182
|
+
const summary = new DocumentSummary(reportSet);
|
|
175
183
|
|
|
176
184
|
expect(Object.fromEntries(summary.tagCounts())).toEqual({
|
|
177
185
|
'eg': {
|
|
@@ -194,8 +202,8 @@ describe("Files summary", () => {
|
|
|
194
202
|
|
|
195
203
|
test("no files", () => {
|
|
196
204
|
const documentData = {}
|
|
197
|
-
const
|
|
198
|
-
const summary = new DocumentSummary(
|
|
205
|
+
const reportSet = testReportSet({}, [], documentData, []);
|
|
206
|
+
const summary = new DocumentSummary(reportSet);
|
|
199
207
|
|
|
200
208
|
expect(summary.getLocalDocuments()).toEqual({
|
|
201
209
|
inline: [],
|
|
@@ -222,8 +230,8 @@ describe("Files summary", () => {
|
|
|
222
230
|
'labelLinkbase.xml': ['labelLinkbase'],
|
|
223
231
|
'unrecognizedLinkbase.xml': ['unrecognizedLinkbase'],
|
|
224
232
|
}
|
|
225
|
-
const
|
|
226
|
-
const summary = new DocumentSummary(
|
|
233
|
+
const reportSet = testReportSet({}, [], documentData, []);
|
|
234
|
+
const summary = new DocumentSummary(reportSet);
|
|
227
235
|
|
|
228
236
|
expect(summary.getLocalDocuments()).toEqual({
|
|
229
237
|
inline: ['docset', 'inline.htm'],
|
|
@@ -237,3 +245,39 @@ describe("Files summary", () => {
|
|
|
237
245
|
});
|
|
238
246
|
});
|
|
239
247
|
});
|
|
248
|
+
|
|
249
|
+
describe("Software credit", () => {
|
|
250
|
+
|
|
251
|
+
test("no credits", () => {
|
|
252
|
+
const softwareCredits = []
|
|
253
|
+
const documentData = {}
|
|
254
|
+
const reportSet = testReportSet({}, [], documentData, softwareCredits);
|
|
255
|
+
const summary = new DocumentSummary(reportSet);
|
|
256
|
+
|
|
257
|
+
expect(summary.getSoftwareCredits()).toEqual([]);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test("one credit", () => {
|
|
261
|
+
const softwareCredits = ["Example credit text"]
|
|
262
|
+
const documentData = {}
|
|
263
|
+
const reportSet = testReportSet({}, [], documentData, softwareCredits);
|
|
264
|
+
const summary = new DocumentSummary(reportSet);
|
|
265
|
+
|
|
266
|
+
expect(summary.getSoftwareCredits()).toEqual(["Example credit text"]);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test("multiple credits", () => {
|
|
270
|
+
const softwareCredits = [
|
|
271
|
+
"Example credit text A",
|
|
272
|
+
"Example credit text B",
|
|
273
|
+
]
|
|
274
|
+
const documentData = {}
|
|
275
|
+
const reportSet = testReportSet({}, [], documentData, softwareCredits);
|
|
276
|
+
const summary = new DocumentSummary(reportSet);
|
|
277
|
+
|
|
278
|
+
expect(summary.getSoftwareCredits()).toEqual([
|
|
279
|
+
"Example credit text A",
|
|
280
|
+
"Example credit text B",
|
|
281
|
+
]);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
// See COPYRIGHT.md for copyright information
|
|
2
2
|
|
|
3
3
|
import $ from 'jquery'
|
|
4
|
-
import FileSaver from 'file-saver'
|
|
5
4
|
import writeXlsxFile from 'write-excel-file'
|
|
6
5
|
import { Fact } from './fact.js';
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
export class TableExport {
|
|
10
|
-
constructor(table,
|
|
9
|
+
constructor(table, reportSet) {
|
|
11
10
|
this._table = table;
|
|
12
|
-
this.
|
|
11
|
+
this._reportSet = reportSet;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
static addHandles(iframe,
|
|
14
|
+
static addHandles(iframe, reportSet) {
|
|
16
15
|
$('table', iframe).each(function () {
|
|
17
16
|
const table = $(this);
|
|
18
|
-
|
|
17
|
+
// Require at least two facts on different rows.
|
|
18
|
+
if (table.find("tr").filter((i, row) => $(row).find(".ixbrl-element").length > 0).length > 1) {
|
|
19
19
|
table.css("position", "relative");
|
|
20
|
-
const exporter = new TableExport(table,
|
|
20
|
+
const exporter = new TableExport(table, reportSet);
|
|
21
21
|
$('<div class="ixbrl-table-handle"><span>Export table</span></div>')
|
|
22
22
|
.appendTo(table)
|
|
23
|
-
.click(
|
|
23
|
+
.on("click", () => exporter.exportTable());
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
_getRawTable() {
|
|
29
29
|
const table = this._table;
|
|
30
|
-
const
|
|
30
|
+
const reportSet = this._reportSet;
|
|
31
31
|
let maxRowLength = 0;
|
|
32
32
|
const rows = [];
|
|
33
33
|
table.find("tr").each(function () {
|
|
@@ -44,7 +44,7 @@ export class TableExport {
|
|
|
44
44
|
let fact = null;
|
|
45
45
|
if (facts.length > 0) {
|
|
46
46
|
const id = facts.first().data('ivids');
|
|
47
|
-
fact =
|
|
47
|
+
fact = reportSet.getItemById(id);
|
|
48
48
|
}
|
|
49
49
|
if (fact instanceof Fact) {
|
|
50
50
|
const cell = { type: "fact", fact: fact};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// See COPYRIGHT.md for copyright information
|
|
2
|
+
|
|
3
|
+
export class TaxonomyNamer {
|
|
4
|
+
constructor(map) {
|
|
5
|
+
this.map = new Map(Array.from(map.entries()).map(([k,v]) => [new RegExp(k), new TaxonomyName(v[0], v[1])]));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
getName(prefix, uri) {
|
|
10
|
+
for (const [re, name] of this.map.entries()) {
|
|
11
|
+
const m = uri.match(re);
|
|
12
|
+
if (m !== null) {
|
|
13
|
+
return name;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return new TaxonomyName(prefix, prefix);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fromQName(qname) {
|
|
20
|
+
return this.getName(qname.prefix, qname.namespace);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
convertQName(qname) {
|
|
24
|
+
const name = this.fromQName(qname)
|
|
25
|
+
return name.prefix + ':' + qname.localname;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class TaxonomyName {
|
|
30
|
+
constructor(prefix, name) {
|
|
31
|
+
this.prefix = prefix;
|
|
32
|
+
this.name = name;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// See COPYRIGHT.md for copyright information
|
|
2
|
+
|
|
3
|
+
import { TaxonomyNamer } from './taxonomynamer.js';
|
|
4
|
+
import { QName } from './qname.js';
|
|
5
|
+
|
|
6
|
+
const prefixMap = {
|
|
7
|
+
"e": "http://example.com/",
|
|
8
|
+
"g": "http://eggsample.com/",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const preferredPrefixMap = new Map([
|
|
12
|
+
[ "http://ex.*\.com/", ["prefix1", "My Example"] ]
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
function qname(s) {
|
|
16
|
+
return new QName(prefixMap, s);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("readableName", () => {
|
|
20
|
+
const namer = new TaxonomyNamer(preferredPrefixMap);
|
|
21
|
+
test("Taxonomy name match", () => {
|
|
22
|
+
expect(namer.fromQName(qname("e:1234")).prefix).toBe("prefix1");
|
|
23
|
+
expect(namer.fromQName(qname("e:1234")).name).toBe("My Example");
|
|
24
|
+
expect(namer.convertQName(qname("e:1234"))).toBe("prefix1:1234");
|
|
25
|
+
});
|
|
26
|
+
test("Unknown taxonomy", () => {
|
|
27
|
+
expect(namer.fromQName(qname("g:1234")).prefix).toBe("g");
|
|
28
|
+
expect(namer.fromQName(qname("g:1234")).name).toBe("g");
|
|
29
|
+
expect(namer.convertQName(qname("g:1234"))).toBe("g:1234");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
@@ -10,3 +10,49 @@ export function TestInspector() {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
TestInspector.prototype = Object.create(Inspector.prototype);
|
|
13
|
+
|
|
14
|
+
expect.extend({
|
|
15
|
+
toEqualDecimal(received, expected) {
|
|
16
|
+
const options = {
|
|
17
|
+
comment: 'decimal.js equality',
|
|
18
|
+
isNot: this.isNot,
|
|
19
|
+
promise: this.promise,
|
|
20
|
+
};
|
|
21
|
+
const pass = received.equals(expected);
|
|
22
|
+
const message = () =>
|
|
23
|
+
this.utils.matcherHint('toEqualDecimals', undefined, undefined, options) +
|
|
24
|
+
'\n\n' +
|
|
25
|
+
`Expected: ${this.isNot ? '(not) ' : ''}${this.utils.printExpected(new Decimal(expected))}\n` +
|
|
26
|
+
`Received: ${this.utils.printReceived(received)}`;
|
|
27
|
+
|
|
28
|
+
return {actual: received, message, pass};
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export function createSimpleFact(id, concept, options=null) {
|
|
34
|
+
options = options || {};
|
|
35
|
+
return {
|
|
36
|
+
[id]: {
|
|
37
|
+
"a": {
|
|
38
|
+
"c": concept,
|
|
39
|
+
"u": options["unit"],
|
|
40
|
+
"p": options["period"],
|
|
41
|
+
},
|
|
42
|
+
"d": options["decimals"],
|
|
43
|
+
"v": options["value"]
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function createNumericFact(id, concept, unit, period, value, decimals) {
|
|
49
|
+
const options = {
|
|
50
|
+
"unit": unit,
|
|
51
|
+
"period": period,
|
|
52
|
+
"value": value
|
|
53
|
+
};
|
|
54
|
+
if (decimals !== undefined) {
|
|
55
|
+
options.decimals = decimals;
|
|
56
|
+
}
|
|
57
|
+
return createSimpleFact(id, concept, options);
|
|
58
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// See COPYRIGHT.md for copyright information
|
|
2
|
+
|
|
3
|
+
import { IXBRL_VIEWER_DATASET_PREFIX, STORAGE_THEME } from "./util";
|
|
4
|
+
|
|
5
|
+
const DARK_THEME = 'dark';
|
|
6
|
+
const LIGHT_THEME = 'light';
|
|
7
|
+
const APP_THEME_DATASET_NAME = `${IXBRL_VIEWER_DATASET_PREFIX}Theme`;
|
|
8
|
+
|
|
9
|
+
function getHtmlElement() {
|
|
10
|
+
return document.querySelector('html');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getVariable(name) {
|
|
14
|
+
const html = getHtmlElement();
|
|
15
|
+
return getComputedStyle(html).getPropertyValue(name);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function setTheme(theme) {
|
|
19
|
+
const html = getHtmlElement();
|
|
20
|
+
html.dataset[APP_THEME_DATASET_NAME] = theme;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getStoredTheme() {
|
|
24
|
+
return localStorage.getItem(STORAGE_THEME);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function storeTheme(theme) {
|
|
28
|
+
localStorage.setItem(STORAGE_THEME, theme);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getTheme() {
|
|
32
|
+
const html = getHtmlElement();
|
|
33
|
+
return html.dataset[APP_THEME_DATASET_NAME];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function initializeTheme() {
|
|
37
|
+
const storedTheme = getStoredTheme();
|
|
38
|
+
if (storedTheme !== null) {
|
|
39
|
+
setTheme(storedTheme);
|
|
40
|
+
} else {
|
|
41
|
+
setTheme(window.matchMedia(`(prefers-color-scheme: ${DARK_THEME})`).matches ? DARK_THEME : LIGHT_THEME);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function toggleTheme() {
|
|
46
|
+
const currentTheme = getTheme();
|
|
47
|
+
const newTheme = currentTheme === LIGHT_THEME ? DARK_THEME : LIGHT_THEME;
|
|
48
|
+
setTheme(newTheme);
|
|
49
|
+
storeTheme(newTheme);
|
|
50
|
+
}
|
|
@@ -1,29 +1,70 @@
|
|
|
1
1
|
// See COPYRIGHT.md for copyright information
|
|
2
2
|
|
|
3
|
+
import { NAMESPACE_ISO4217 } from "./util";
|
|
3
4
|
import i18next from "i18next";
|
|
4
|
-
import {
|
|
5
|
+
import { utr } from "./utr";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Transforms measure qname into title case label (or currency symbol, if applicable).
|
|
9
|
+
* @return {String} Measure Label
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
function measureLabel(report, measure) {
|
|
13
|
+
const qname = report.qname(measure);
|
|
14
|
+
if (qname.namespace === NAMESPACE_ISO4217) {
|
|
15
|
+
// Prefer a name from our own i18n resources for currencies
|
|
16
|
+
const keyi18n = `currencies:unitFormat${qname.localname}`;
|
|
17
|
+
if (i18next.exists(keyi18n)) {
|
|
18
|
+
return i18next.t(keyi18n);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Pick symbol from UTR ...
|
|
22
|
+
const utrEntry = utr.get(qname);
|
|
23
|
+
if (utrEntry !== undefined) {
|
|
24
|
+
if (utrEntry.symbol !== undefined) {
|
|
25
|
+
// ... but disambiguate "$" symbol
|
|
26
|
+
return utrEntry.symbol == '$' ? `${qname.localname} $` : utrEntry.symbol;
|
|
27
|
+
}
|
|
28
|
+
// Fall back to name
|
|
29
|
+
return utrEntry.name;
|
|
30
|
+
}
|
|
31
|
+
// Otherwise the measure is not in the UTR so fallback to unitId
|
|
32
|
+
if (measure.includes(':')) {
|
|
33
|
+
return measure.split(':')[1];
|
|
34
|
+
}
|
|
35
|
+
return measure;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function measureName(report, measure) {
|
|
39
|
+
const qname = report.qname(measure);
|
|
40
|
+
const utrEntry = utr.get(qname);
|
|
41
|
+
return utrEntry?.name;
|
|
42
|
+
}
|
|
5
43
|
|
|
6
44
|
export class Unit {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
this._report = report;
|
|
45
|
+
constructor(reportSet, unitKey) {
|
|
46
|
+
this._reportSet = reportSet;
|
|
10
47
|
this._value = unitKey;
|
|
11
48
|
const split = unitKey
|
|
12
49
|
.split(/[()]/ig).join('') // TODO: replace with .replaceAll(/[()]/ig,'') when no longer supporting node 14
|
|
13
50
|
.split('/');
|
|
14
51
|
this._numerators = split[0].split('*');
|
|
15
52
|
this._denominators = split.length > 1 ? split[1].split('*') : [];
|
|
16
|
-
this._isMonetary =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
53
|
+
this._isMonetary =
|
|
54
|
+
this._denominators.length === 0 &&
|
|
55
|
+
this._numerators.length === 1 &&
|
|
56
|
+
this._reportSet.qname(this._numerators[0]).namespace === NAMESPACE_ISO4217;
|
|
57
|
+
this._label = split
|
|
58
|
+
.map(measure => {
|
|
59
|
+
const part = measure
|
|
60
|
+
.split('*')
|
|
61
|
+
.map(x => measureLabel(this._reportSet, x))
|
|
62
|
+
.join('*');
|
|
21
63
|
return part.includes('*') ? `(${part})` : part;
|
|
22
|
-
})
|
|
23
|
-
|
|
64
|
+
})
|
|
65
|
+
.join('/');
|
|
24
66
|
}
|
|
25
67
|
|
|
26
|
-
|
|
27
68
|
/**
|
|
28
69
|
* Returns whether any of the numerators are an iso4217 monetary measure.
|
|
29
70
|
* @return {Boolean}
|
|
@@ -41,32 +82,49 @@ export class Unit {
|
|
|
41
82
|
}
|
|
42
83
|
|
|
43
84
|
/**
|
|
44
|
-
* Returns the
|
|
45
|
-
* @return {String}
|
|
85
|
+
* Returns the OIM format string representing the unit
|
|
86
|
+
* @return {String} OIM format unit string
|
|
46
87
|
*/
|
|
47
|
-
|
|
48
|
-
return this.
|
|
88
|
+
value() {
|
|
89
|
+
return this._value;
|
|
49
90
|
}
|
|
50
91
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const qname = this._report.qname(measure);
|
|
58
|
-
if (qname.namespace === "http://www.xbrl.org/2003/iso4217") {
|
|
59
|
-
return i18next.t(`currencies:unitFormat${qname.localname}`, {defaultValue: qname.localname});
|
|
92
|
+
measureHTML(m) {
|
|
93
|
+
const span = document.createElement("span");
|
|
94
|
+
const name = measureName(this._reportSet, m);
|
|
95
|
+
if (name !== undefined) {
|
|
96
|
+
span.setAttribute("title", name);
|
|
97
|
+
span.classList.add("measure");
|
|
60
98
|
}
|
|
61
|
-
|
|
99
|
+
span.append(document.createTextNode(measureLabel(this._reportSet, m)));
|
|
100
|
+
return span;
|
|
62
101
|
}
|
|
63
102
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
103
|
+
partsHTML(parts) {
|
|
104
|
+
const span = document.createElement("span");
|
|
105
|
+
if (parts.length > 1) {
|
|
106
|
+
span.appendChild(document.createTextNode("("));
|
|
107
|
+
}
|
|
108
|
+
for (const [i, m] of parts.entries()) {
|
|
109
|
+
span.appendChild(this.measureHTML(m));
|
|
110
|
+
if (i < parts.length - 1) {
|
|
111
|
+
span.appendChild(document.createTextNode(" * "))
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (parts.length > 1) {
|
|
115
|
+
span.appendChild(document.createTextNode(")"));
|
|
116
|
+
}
|
|
117
|
+
return span;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
html() {
|
|
121
|
+
const span = document.createElement("span");
|
|
122
|
+
span.append(this.partsHTML(this._numerators));
|
|
123
|
+
if (this._denominators.length > 0) {
|
|
124
|
+
span.append(document.createTextNode(" / "));
|
|
125
|
+
span.append(this.partsHTML(this._denominators));
|
|
126
|
+
}
|
|
127
|
+
return span;
|
|
70
128
|
}
|
|
71
129
|
}
|
|
72
130
|
|