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
|
@@ -2,315 +2,444 @@
|
|
|
2
2
|
|
|
3
3
|
import interact from 'interactjs'
|
|
4
4
|
import $ from 'jquery'
|
|
5
|
-
import {
|
|
5
|
+
import { ReportSet } from "./reportset.js";
|
|
6
6
|
import { Viewer, DocumentTooLargeError } from "./viewer.js";
|
|
7
7
|
import { Inspector } from "./inspector.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
import { initializeTheme } from './theme.js';
|
|
9
|
+
import { TaxonomyNamer } from './taxonomynamer.js';
|
|
10
|
+
import { FEATURE_GUIDE_LINK, FEATURE_REVIEW, FEATURE_SUPPORT_LINK, FEATURE_SURVEY_LINK, USER_GUIDE_URL, moveNonAppAttributes } from "./util";
|
|
11
|
+
|
|
12
|
+
const featureFalsyValues = new Set([undefined, null, '', 'false', false]);
|
|
13
|
+
|
|
14
|
+
export class iXBRLViewer {
|
|
15
|
+
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this._staticFeatures = {};
|
|
18
|
+
this._dynamicFeatures = {};
|
|
19
|
+
this._plugins = [];
|
|
20
|
+
this.inspector = new Inspector(this);
|
|
21
|
+
this.viewer = null;
|
|
22
|
+
options = options || {};
|
|
23
|
+
const defaults = {
|
|
24
|
+
continuationElementLimit: 10000,
|
|
25
|
+
showValidationWarningOnStart: false,
|
|
26
|
+
}
|
|
27
|
+
this.options = {...defaults, ...options};
|
|
18
28
|
}
|
|
19
|
-
this.options = {...defaults, ...options};
|
|
20
|
-
}
|
|
21
29
|
|
|
22
|
-
/*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
30
|
+
/*
|
|
31
|
+
* Adds a plugin to the viewer. The plugin should be an object with one or
|
|
32
|
+
* more of the methods listed below, which will be called by the viewer.
|
|
33
|
+
*
|
|
34
|
+
* preProcessiXBRL(bodyElement, docIndex)
|
|
35
|
+
*
|
|
36
|
+
* Called upon viewer intialisation, once for each iXBRL document. bodyElement
|
|
37
|
+
* is a DOM object for the body element. docIndex is the index of the document
|
|
38
|
+
* within the document set.
|
|
39
|
+
*
|
|
40
|
+
* updateViewerStyleElement(styleElts)
|
|
41
|
+
*
|
|
42
|
+
* styleElts is a JQuery object consisting of the viewer style elements for
|
|
43
|
+
* each document in the document set. Additional CSS can be appended to the
|
|
44
|
+
* contents, or additional header elements inserted relative to the provided
|
|
45
|
+
* style element.
|
|
46
|
+
*
|
|
47
|
+
* extendDisplayOptionsMenu(menu)
|
|
48
|
+
*
|
|
49
|
+
* Called when the display options menu is created or recreated. menu is a
|
|
50
|
+
* Menu object, and can be modified to add additional menu items.
|
|
51
|
+
*
|
|
52
|
+
* extendHighlightKey(key)
|
|
53
|
+
*
|
|
54
|
+
* Called when the highlight color key is created. key is an array of labels,
|
|
55
|
+
* which can be modified or extended.
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
58
|
+
registerPlugin(plugin) {
|
|
59
|
+
this._plugins.push(plugin);
|
|
60
|
+
}
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
callPluginMethod(methodName, ...args) {
|
|
63
|
+
for (const p of this._plugins) {
|
|
64
|
+
if (typeof p[methodName] === 'function') {
|
|
65
|
+
p[methodName](...args);
|
|
66
|
+
}
|
|
59
67
|
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
68
|
+
}
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await p[methodName](...args);
|
|
70
|
+
pluginPromise(methodName, ...args) {
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
/* Call promises in turn */
|
|
73
|
+
(async () => {
|
|
74
|
+
for (const p of this._plugins) {
|
|
75
|
+
if (typeof p[methodName] === 'function') {
|
|
76
|
+
await p[methodName](...args);
|
|
77
|
+
}
|
|
72
78
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
})().then(() => {
|
|
80
|
+
resolve();
|
|
81
|
+
});
|
|
76
82
|
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
83
|
+
}
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
featureNames.forEach(f => {
|
|
85
|
-
featureMap[f] = true;
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Enable/disable features based on query string
|
|
89
|
-
const urlParams = new URLSearchParams(queryString);
|
|
90
|
-
urlParams.forEach((value, key) => {
|
|
91
|
-
// Do nothing if feature has already been disabled by query
|
|
92
|
-
if (featureMap[key] !== false) {
|
|
93
|
-
// Disable feature if value is exactly 'false', anything else enables the feature
|
|
94
|
-
featureMap[key] = value !== 'false';
|
|
85
|
+
setFeatures(features, queryString) {
|
|
86
|
+
this._staticFeatures = {}
|
|
87
|
+
for (const [key, value] of Object.entries(features)) {
|
|
88
|
+
this._staticFeatures[key] = value;
|
|
95
89
|
}
|
|
96
|
-
});
|
|
97
90
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
const urlParams = new URLSearchParams(queryString);
|
|
92
|
+
this._dynamicFeatures = {}
|
|
93
|
+
urlParams.forEach((value, key) => {
|
|
94
|
+
if (value === '') {
|
|
95
|
+
if (this._dynamicFeatures[key] === undefined) {
|
|
96
|
+
value = 'true'
|
|
97
|
+
} else {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
this._dynamicFeatures[key] = value;
|
|
102
|
+
});
|
|
101
103
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
104
|
+
|
|
105
|
+
getStaticFeatureValue(featureName) {
|
|
106
|
+
return this._staticFeatures[featureName];
|
|
106
107
|
}
|
|
107
|
-
}
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
getFeatureValue(featureName) {
|
|
110
|
+
if (this._dynamicFeatures[featureName]) {
|
|
111
|
+
return this._dynamicFeatures[featureName];
|
|
112
|
+
}
|
|
113
|
+
return this.getStaticFeatureValue(featureName);
|
|
114
|
+
}
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
+
isFeatureEnabled(featureName) {
|
|
117
|
+
return !featureFalsyValues.has(this.getFeatureValue(featureName));
|
|
118
|
+
}
|
|
116
119
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
$(require('../html/inspector.html')).prependTo('body');
|
|
120
|
-
var inspector_css = require('css-loader!../less/inspector.less').toString();
|
|
121
|
-
$('<style id="ixv-style"></style>')
|
|
122
|
-
.prop("type", "text/css")
|
|
123
|
-
.text(inspector_css)
|
|
124
|
-
.appendTo('head');
|
|
125
|
-
$('<link id="ixv-favicon" type="image/x-icon" rel="shortcut icon" />')
|
|
126
|
-
.attr('href', require('../img/favicon.ico'))
|
|
127
|
-
.appendTo('head');
|
|
128
|
-
|
|
129
|
-
try {
|
|
130
|
-
$('.inspector-foot .version').text(__VERSION__);
|
|
120
|
+
isStaticFeatureEnabled(featureName) {
|
|
121
|
+
return !featureFalsyValues.has(this.getStaticFeatureValue(featureName));
|
|
131
122
|
}
|
|
132
|
-
|
|
133
|
-
|
|
123
|
+
|
|
124
|
+
isReviewModeEnabled() {
|
|
125
|
+
return this.isFeatureEnabled(FEATURE_REVIEW);
|
|
134
126
|
}
|
|
135
|
-
}
|
|
136
127
|
|
|
137
|
-
|
|
138
|
-
|
|
128
|
+
getGuideLinkUrl() {
|
|
129
|
+
if (!this.isStaticFeatureEnabled(FEATURE_GUIDE_LINK)) {
|
|
130
|
+
return USER_GUIDE_URL;
|
|
131
|
+
}
|
|
132
|
+
return this.resolveRelativeUrl(this.getStaticFeatureValue(FEATURE_GUIDE_LINK));
|
|
133
|
+
}
|
|
139
134
|
|
|
140
|
-
|
|
135
|
+
getSupportLinkUrl() {
|
|
136
|
+
if (!this.isStaticFeatureEnabled(FEATURE_SUPPORT_LINK)) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return this.resolveRelativeUrl(this.getStaticFeatureValue(FEATURE_SUPPORT_LINK));
|
|
140
|
+
}
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
getSurveyLinkUrl() {
|
|
143
|
+
if (!this.isStaticFeatureEnabled(FEATURE_SURVEY_LINK)) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return this.resolveRelativeUrl(this.getStaticFeatureValue(FEATURE_SURVEY_LINK));
|
|
147
|
+
}
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
isViewerEnabled() {
|
|
150
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
151
|
+
return (urlParams.get('disable-viewer') ?? 'false') === 'false';
|
|
150
152
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
|
|
154
|
+
// Resolves URL relative to the config file
|
|
155
|
+
resolveRelativeUrl(url) {
|
|
156
|
+
if (this.options.configUrl === undefined) {
|
|
157
|
+
return url;
|
|
158
|
+
}
|
|
159
|
+
const resolvedUrl = new URL(url, this.options.configUrl.href);
|
|
160
|
+
return resolvedUrl.href;
|
|
153
161
|
}
|
|
154
|
-
|
|
155
|
-
|
|
162
|
+
|
|
163
|
+
_loadInspectorHTML() {
|
|
164
|
+
/* Insert HTML and CSS styles into body */
|
|
165
|
+
const footerLogoHtml = this.runtimeConfig.skin?.footerLogoHtml ?? require("../html/footer-logo.html");
|
|
166
|
+
$(require('../html/inspector.html'))
|
|
167
|
+
.prependTo('body')
|
|
168
|
+
.find("#footer-logo").html(footerLogoHtml);
|
|
169
|
+
const inspector_css = require('../less/inspector.less').toString();
|
|
170
|
+
$('<style id="ixv-style"></style>')
|
|
171
|
+
.prop("type", "text/css")
|
|
172
|
+
.text(inspector_css)
|
|
173
|
+
.appendTo('head');
|
|
174
|
+
if (this.runtimeConfig.skin?.stylesheetUrl !== undefined) {
|
|
175
|
+
$('<link rel="stylesheet" id="ixv-style-skin" />')
|
|
176
|
+
.attr("href", this.resolveRelativeUrl(this.runtimeConfig.skin.stylesheetUrl))
|
|
177
|
+
.appendTo('head');
|
|
178
|
+
}
|
|
179
|
+
const favIconUrl = this.runtimeConfig.skin?.faviconUrl !== undefined ? this.resolveRelativeUrl(this.runtimeConfig.skin.faviconUrl) : require("../img/favicon.ico");
|
|
180
|
+
$('<link id="ixv-favicon" type="image/x-icon" rel="shortcut icon" />')
|
|
181
|
+
.attr('href', favIconUrl)
|
|
182
|
+
.appendTo('head');
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
$('.inspector-foot .version').text(__VERSION__);
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
// ReferenceError if __VERSION__ not defined
|
|
189
|
+
}
|
|
156
190
|
}
|
|
157
191
|
|
|
158
|
-
|
|
192
|
+
_reparentDocument() {
|
|
193
|
+
const iframeContainer = $('#ixv #iframe-container');
|
|
194
|
+
|
|
195
|
+
const iframe = $('<iframe title="iXBRL document view" tabindex="0"/>')
|
|
196
|
+
.data("report-index", 0)
|
|
197
|
+
.appendTo(iframeContainer)[0];
|
|
198
|
+
|
|
199
|
+
const doc = iframe.contentDocument || iframe.contentWindow.document;
|
|
200
|
+
doc.open();
|
|
201
|
+
doc.write("<!DOCTYPE html><html><head><title></title></head><body></body></html>");
|
|
202
|
+
doc.close();
|
|
203
|
+
|
|
204
|
+
let docTitle = $('title').text();
|
|
205
|
+
if (docTitle !== "") {
|
|
206
|
+
docTitle = `Inline Viewer - ${docTitle}`;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
docTitle = "Inline Viewer";
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
$('head')
|
|
214
|
+
.children().not("script, style#ixv-style, link#ixv-style-skin, link#ixv-favicon").appendTo($(iframe).contents().find('head'));
|
|
215
|
+
|
|
216
|
+
$('<title>').text(docTitle).appendTo($('head'));
|
|
159
217
|
|
|
160
|
-
|
|
218
|
+
/* Due to self-closing tags, our script tags may not be a direct child of
|
|
219
|
+
* the body tag in an HTML DOM, so move them so that they are */
|
|
220
|
+
$('body script').appendTo($('body'));
|
|
161
221
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
222
|
+
const html = $('html');
|
|
223
|
+
const body = $('body');
|
|
224
|
+
const iframeHtml = $(iframe).contents().find('html');
|
|
225
|
+
const iframeBody = $(iframe).contents().find('body');
|
|
226
|
+
moveNonAppAttributes(html.get(0), iframeHtml.get(0));
|
|
227
|
+
moveNonAppAttributes(body.get(0), iframeBody.get(0));
|
|
228
|
+
html.attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
|
167
229
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
230
|
+
body.children().not("script").not('#ixv').not(iframeContainer).appendTo(iframeBody);
|
|
231
|
+
|
|
232
|
+
/* Avoid any inline styles on the old body interfering with the inspector */
|
|
233
|
+
body.removeAttr('style');
|
|
234
|
+
return iframe;
|
|
172
235
|
}
|
|
173
236
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
237
|
+
_getTaxonomyData() {
|
|
238
|
+
for (let i = document.body.children.length - 1; i >= 0; i--) {
|
|
239
|
+
const elt = document.body.children[i];
|
|
240
|
+
if (elt.tagName.toUpperCase() === 'SCRIPT' && elt.getAttribute("type") === 'application/x.ixbrl-viewer+json') {
|
|
241
|
+
return elt.innerHTML;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
178
246
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (elt.tagName.toUpperCase() == 'SCRIPT' && elt.getAttribute("type") == 'application/x.ixbrl-viewer+json') {
|
|
183
|
-
return elt.innerHTML;
|
|
247
|
+
_checkDocumentSetBrowserSupport() {
|
|
248
|
+
if (document.location.protocol === 'file:') {
|
|
249
|
+
alert("Displaying iXBRL document sets from local files is not supported. Please view the viewer files using a web server.");
|
|
184
250
|
}
|
|
185
251
|
}
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
252
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
253
|
+
_loadRuntimeConfig() {
|
|
254
|
+
return new Promise((resolve, reject) => {
|
|
255
|
+
if (this.options.configUrl === undefined) {
|
|
256
|
+
resolve({});
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
fetch(this.options.configUrl)
|
|
260
|
+
.then((resp) => {
|
|
261
|
+
switch (resp.status) {
|
|
262
|
+
case 200:
|
|
263
|
+
return resp.json();
|
|
264
|
+
case 404:
|
|
265
|
+
return Promise.resolve({});
|
|
266
|
+
default:
|
|
267
|
+
return Promise.reject(`Fetch of ${this.options.configUrl} failed: ${resp.status}`);
|
|
268
|
+
};
|
|
269
|
+
})
|
|
270
|
+
.then((data) => {
|
|
271
|
+
resolve(data);
|
|
272
|
+
})
|
|
273
|
+
.catch((err) => {
|
|
274
|
+
console.log(err);
|
|
275
|
+
resolve({});
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
});
|
|
192
279
|
}
|
|
193
|
-
}
|
|
194
280
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
281
|
+
load() {
|
|
282
|
+
const iv = this;
|
|
283
|
+
const inspector = this.inspector;
|
|
284
|
+
|
|
285
|
+
this._loadRuntimeConfig().then((runtimeConfig) => {
|
|
286
|
+
this.runtimeConfig = runtimeConfig;
|
|
287
|
+
initializeTheme();
|
|
198
288
|
|
|
199
|
-
|
|
289
|
+
const stubViewer = $('body').hasClass('ixv-stub-viewer');
|
|
200
290
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
291
|
+
// If viewer is disabled, but not in stub viewer mode, just abort
|
|
292
|
+
// loading to leave the iXBRL file as-is
|
|
293
|
+
if (!iv.isViewerEnabled() && !stubViewer) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
205
296
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (!stubViewer) {
|
|
210
|
-
iframes = $(iv._reparentDocument());
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
iframes = $();
|
|
214
|
-
}
|
|
215
|
-
if (parsedTaxonomyData === null) {
|
|
216
|
-
$('#ixv .loader .text').text("Error: Could not find viewer data");
|
|
217
|
-
$('#ixv .loader').removeClass("loading");
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
const report = new iXBRLReport(parsedTaxonomyData);
|
|
221
|
-
const ds = report.documentSetFiles();
|
|
222
|
-
var hasExternalIframe = false;
|
|
223
|
-
for (var i = stubViewer ? 0 : 1; i < ds.length; i++) {
|
|
224
|
-
const iframe = $("<iframe />").attr("src", ds[i]).appendTo("#ixv #iframe-container");
|
|
225
|
-
iframes = iframes.add(iframe);
|
|
226
|
-
hasExternalIframe = true;
|
|
227
|
-
}
|
|
228
|
-
if (hasExternalIframe) {
|
|
229
|
-
iv._checkDocumentSetBrowserSupport();
|
|
230
|
-
}
|
|
297
|
+
// Loading mask starts here
|
|
298
|
+
iv._loadInspectorHTML();
|
|
299
|
+
let iframes = $();
|
|
231
300
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
.then(() => {
|
|
252
|
-
interact('#viewer-pane').resizable({
|
|
253
|
-
edges: { left: false, right: ".resize", bottom: false, top: false},
|
|
254
|
-
restrictEdges: {
|
|
255
|
-
outer: 'parent',
|
|
256
|
-
endOnly: true,
|
|
257
|
-
},
|
|
258
|
-
restrictSize: {
|
|
259
|
-
min: { width: 100 }
|
|
260
|
-
},
|
|
261
|
-
})
|
|
262
|
-
.on('resizestart', function (event) {
|
|
263
|
-
$('#ixv').css("pointer-events", "none");
|
|
264
|
-
})
|
|
265
|
-
.on('resizemove', function (event) {
|
|
266
|
-
var target = event.target;
|
|
267
|
-
var w = 100 * event.rect.width / $(target).parent().width();
|
|
268
|
-
target.style.width = w + '%';
|
|
269
|
-
$('#inspector').css('width', (100 - w) + '%');
|
|
270
|
-
})
|
|
271
|
-
.on('resizeend', function (event) {
|
|
272
|
-
$('#ixv').css("pointer-events", "auto");
|
|
273
|
-
});
|
|
274
|
-
$('#ixv .loader').remove();
|
|
301
|
+
// We need to parse JSON first so that we can determine feature enablement before loading begins.
|
|
302
|
+
const taxonomyData = iv._getTaxonomyData();
|
|
303
|
+
const parsedTaxonomyData = taxonomyData && JSON.parse(taxonomyData);
|
|
304
|
+
let features = parsedTaxonomyData?.features;
|
|
305
|
+
if (!features) {
|
|
306
|
+
features = {};
|
|
307
|
+
}
|
|
308
|
+
// `features` was previously an array of flag values
|
|
309
|
+
// Support this for backwards compatability
|
|
310
|
+
else if (Array.isArray(features)) {
|
|
311
|
+
features = features.reduce((obj, val) => {
|
|
312
|
+
obj[val] = true;
|
|
313
|
+
return obj;
|
|
314
|
+
}, {});
|
|
315
|
+
}
|
|
316
|
+
if (this.runtimeConfig.features !== undefined) {
|
|
317
|
+
features = {...this.runtimeConfig.features, features};
|
|
318
|
+
}
|
|
319
|
+
iv.setFeatures(features, window.location.search);
|
|
275
320
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
321
|
+
const reportSet = new ReportSet(parsedTaxonomyData);
|
|
322
|
+
reportSet.taxonomyNamer = new TaxonomyNamer(new Map(Object.entries(this.runtimeConfig.taxonomyNames ?? {})));
|
|
323
|
+
|
|
324
|
+
// Viewer disabled in stub viewer mode => redirect to first iXBRL document
|
|
325
|
+
if (!iv.isViewerEnabled()) {
|
|
326
|
+
window.location.replace(reportSet.reportFiles()[0].file);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (parsedTaxonomyData === null) {
|
|
331
|
+
$('#ixv .loader .text').text("Error: Could not find viewer data");
|
|
332
|
+
$('#ixv .loader').removeClass("loading");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (!stubViewer) {
|
|
337
|
+
iframes = $(iv._reparentDocument());
|
|
338
|
+
}
|
|
339
|
+
const ds = reportSet.reportFiles();
|
|
340
|
+
let hasExternalIframe = false;
|
|
341
|
+
for (let i = stubViewer ? 0 : 1; i < ds.length; i++) {
|
|
342
|
+
const iframe = $('<iframe tabindex="0" />').attr("src", ds[i].file).data("report-index", ds[i].index).appendTo("#ixv #iframe-container");
|
|
343
|
+
iframes = iframes.add(iframe);
|
|
344
|
+
hasExternalIframe = true;
|
|
345
|
+
}
|
|
346
|
+
if (hasExternalIframe) {
|
|
347
|
+
iv._checkDocumentSetBrowserSupport();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const progress = stubViewer ? 'Loading iXBRL Report' : 'Loading iXBRL Viewer';
|
|
351
|
+
iv.setProgress(progress).then(() => {
|
|
352
|
+
/* Poll for iframe load completing - there doesn't seem to be a reliable event that we can use */
|
|
353
|
+
const timer = setInterval(() => {
|
|
354
|
+
let complete = true;
|
|
355
|
+
iframes.each((n, iframe) => {
|
|
356
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
|
357
|
+
if ((iframeDoc.readyState !== 'complete' && iframeDoc.readyState !== 'interactive') || $(iframe).contents().find("body").children().length === 0) {
|
|
358
|
+
complete = false;
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
if (complete) {
|
|
362
|
+
clearInterval(timer);
|
|
363
|
+
|
|
364
|
+
iframes.each((n, iframe) => {
|
|
365
|
+
const htmlNode = $(iframe).contents().find('html');
|
|
366
|
+
// A schema valid report should not have a lang attribute on the html element.
|
|
367
|
+
// However, if the report is not schema valid, we shouldn't override it.
|
|
368
|
+
if (htmlNode.attr('lang') === undefined) {
|
|
369
|
+
// If the report has an XML lang attribute, use it as the HTML lang for screen readers.
|
|
370
|
+
// If the language of the report can't be detected, set it to an empty string to avoid
|
|
371
|
+
// inheriting the lang of the application HTML node (which is set to the UI language).
|
|
372
|
+
const docLang = htmlNode.attr('xml:lang') || '';
|
|
373
|
+
htmlNode.attr('lang', docLang);
|
|
280
374
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
.
|
|
285
|
-
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
const viewer = new Viewer(iv, iframes, reportSet);
|
|
378
|
+
iv.viewer = viewer
|
|
379
|
+
|
|
380
|
+
viewer.initialize()
|
|
381
|
+
.then(() => inspector.initialize(reportSet, viewer))
|
|
382
|
+
.then(() => {
|
|
383
|
+
interact('#viewer-pane').resizable({
|
|
384
|
+
edges: { left: false, right: ".resize", bottom: false, top: false},
|
|
385
|
+
restrictEdges: {
|
|
386
|
+
outer: 'parent',
|
|
387
|
+
endOnly: true,
|
|
388
|
+
},
|
|
389
|
+
restrictSize: {
|
|
390
|
+
min: { width: 100 }
|
|
391
|
+
},
|
|
392
|
+
})
|
|
393
|
+
.on('resizestart', () =>
|
|
394
|
+
$('#ixv').css("pointer-events", "none")
|
|
395
|
+
)
|
|
396
|
+
.on('resizemove', (event) => {
|
|
397
|
+
const target = event.target;
|
|
398
|
+
const w = 100 * event.rect.width / $(target).parent().width();
|
|
399
|
+
target.style.width = `${w}%`;
|
|
400
|
+
$('#inspector').css('width', `${100 - w}%`);
|
|
401
|
+
})
|
|
402
|
+
.on('resizeend', (event) =>
|
|
403
|
+
$('#ixv').css("pointer-events", "auto")
|
|
404
|
+
);
|
|
286
405
|
$('#ixv .loader').remove();
|
|
287
|
-
$('#inspector').addClass('failed-to-load');
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
throw err;
|
|
291
|
-
}
|
|
292
406
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
407
|
+
/* Focus on fact specified in URL fragment, if any */
|
|
408
|
+
if (iv.options.showValidationWarningOnStart) {
|
|
409
|
+
inspector.showValidationWarning();
|
|
410
|
+
}
|
|
411
|
+
viewer.postLoadAsync();
|
|
412
|
+
inspector.postLoadAsync();
|
|
413
|
+
})
|
|
414
|
+
.catch(err => {
|
|
415
|
+
if (err instanceof DocumentTooLargeError) {
|
|
416
|
+
$('#ixv .loader').remove();
|
|
417
|
+
$('#inspector').addClass('failed-to-load');
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
throw err;
|
|
421
|
+
}
|
|
299
422
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
}, 250);
|
|
426
|
+
});
|
|
427
|
+
}, 0);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/* Update the progress message during initial load. Returns a Promise which
|
|
431
|
+
* resolves once the message is actually displayed */
|
|
432
|
+
setProgress(msg) {
|
|
433
|
+
return new Promise((resolve, reject) => {
|
|
434
|
+
/* We need to do a double requestAnimationFrame, as we need to get the
|
|
435
|
+
* message up before the ensuing thread-blocking work
|
|
436
|
+
* https://bugs.chromium.org/p/chromium/issues/detail?id=675795
|
|
437
|
+
*/
|
|
438
|
+
window.requestAnimationFrame(() => {
|
|
439
|
+
console.log(`%c [Progress] ${msg} `, 'background: #77d1c8; color: black;');
|
|
440
|
+
$('#ixv .loader .text').text(msg);
|
|
441
|
+
window.requestAnimationFrame(() => resolve());
|
|
313
442
|
});
|
|
314
443
|
});
|
|
315
|
-
}
|
|
444
|
+
}
|
|
316
445
|
}
|