@teipublisher/pb-components 2.26.1-next.2 → 3.0.0-next-4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/docker-cypress.yml +54 -0
- package/.github/workflows/main.yml +6 -4
- package/.github/workflows/node.js.yml +56 -21
- package/.github/workflows/release.js.yml +19 -17
- package/.releaserc.json +1 -1
- package/CHANGELOG.md +351 -9
- package/Dockerfile +78 -70
- package/README.md +112 -4
- package/css/components.css +5 -5
- package/css/gridjs/mermaid.min.css +1 -1
- package/css/leaflet/Control.Geocoder.css +1 -126
- package/css/leaflet/images/layers.png +0 -0
- package/css/tify/tify.css +6 -5
- package/css/tom-select/tom-select.bootstrap4.min.css +1 -1
- package/css/tom-select/tom-select.bootstrap5.min.css +1 -1
- package/css/tom-select/tom-select.default.min.css +1 -1
- package/css/tom-select/tom-select.default.min.css.map +1 -0
- package/css/tom-select/tom-select.min.css +1 -1
- package/cypress.config.js +84 -0
- package/dist/api.html +1 -1
- package/dist/css/design-system.css +607 -0
- package/dist/demo/bundle-test.html +4 -3
- package/dist/demo/components.css +46 -1
- package/dist/demo/design-system.html +710 -0
- package/dist/demo/dts-client.html +2 -2
- package/dist/demo/pb-autocomplete.html +23 -11
- package/dist/demo/pb-autocomplete2.html +66 -55
- package/dist/demo/pb-autocomplete3.html +17 -8
- package/dist/demo/pb-blacklab-highlight.html +28 -11
- package/dist/demo/pb-blacklab-results.html +3 -2
- package/dist/demo/pb-browse-docs.html +24 -24
- package/dist/demo/pb-browse-docs2.html +3 -3
- package/dist/demo/pb-clipboard.html +32 -28
- package/dist/demo/pb-code-editor.html +6 -6
- package/dist/demo/pb-code-highlight.html +63 -63
- package/dist/demo/pb-codepen.html +1 -1
- package/dist/demo/pb-collapse.html +1 -1
- package/dist/demo/pb-collapse2.html +2 -2
- package/dist/demo/pb-combo-box.html +135 -130
- package/dist/demo/pb-custom-form.html +64 -55
- package/dist/demo/pb-dialog.html +12 -6
- package/dist/demo/pb-document.html +1 -1
- package/dist/demo/pb-download.html +68 -59
- package/dist/demo/pb-drawer.html +67 -46
- package/dist/demo/pb-drawer2.html +65 -58
- package/dist/demo/pb-edit-app.html +2 -2
- package/dist/demo/pb-edit-xml.html +1 -1
- package/dist/demo/pb-facsimile-2.html +26 -11
- package/dist/demo/pb-facsimile-3.html +25 -10
- package/dist/demo/pb-facsimile-dedup-test-2.html +48 -0
- package/dist/demo/pb-facsimile-dedup-test.html +48 -0
- package/dist/demo/pb-facsimile.html +4 -4
- package/dist/demo/pb-formula.html +1 -1
- package/dist/demo/pb-grid.html +22 -8
- package/dist/demo/pb-highlight.html +2 -2
- package/dist/demo/pb-i18n-simple.html +1 -0
- package/dist/demo/pb-i18n.html +15 -5
- package/dist/demo/pb-image-strip-standalone.html +2 -2
- package/dist/demo/pb-image-strip-view.html +2 -2
- package/dist/demo/pb-leaflet-map.html +3 -3
- package/dist/demo/pb-leaflet-map2.html +2 -2
- package/dist/demo/pb-leaflet-map3.html +3 -3
- package/dist/demo/pb-link.html +1 -1
- package/dist/demo/pb-load.html +2 -6
- package/dist/demo/pb-login.html +1 -3
- package/dist/demo/pb-manage-odds.html +9 -4
- package/dist/demo/pb-markdown.html +1 -1
- package/dist/demo/pb-media-query.html +2 -2
- package/dist/demo/pb-mei.html +2 -2
- package/dist/demo/pb-mei2.html +2 -2
- package/dist/demo/pb-message.html +2 -3
- package/dist/demo/pb-odd-editor.html +54 -52
- package/dist/demo/pb-page-header.html +27 -0
- package/dist/demo/pb-popover.html +1 -1
- package/dist/demo/pb-print-preview.html +2 -2
- package/dist/demo/pb-progress.html +4 -4
- package/dist/demo/pb-repeat.html +32 -36
- package/dist/demo/pb-search.html +16 -5
- package/dist/demo/pb-search2.html +4 -4
- package/dist/demo/pb-search3.html +3 -3
- package/dist/demo/pb-search4.html +3 -3
- package/dist/demo/pb-select-feature.html +4 -4
- package/dist/demo/pb-select-feature2.html +4 -4
- package/dist/demo/pb-select-feature3.html +2 -2
- package/dist/demo/pb-select-i18n.html +58 -53
- package/dist/demo/pb-select-odd.html +1 -1
- package/dist/demo/pb-select.html +190 -75
- package/dist/demo/pb-select2.html +91 -37
- package/dist/demo/pb-select3.html +109 -41
- package/dist/demo/pb-svg.html +1 -1
- package/dist/demo/pb-table-grid.html +26 -15
- package/dist/demo/pb-tabs.html +15 -7
- package/dist/demo/pb-tify.html +7 -7
- package/dist/demo/pb-timeline.html +1 -1
- package/dist/demo/pb-timeline2.html +1 -1
- package/dist/demo/pb-toggle-feature.html +26 -23
- package/dist/demo/pb-toggle-feature2.html +4 -4
- package/dist/demo/pb-toggle-feature3.html +2 -2
- package/dist/demo/pb-toggle-feature4.html +56 -54
- package/dist/demo/pb-version.html +2 -2
- package/dist/demo/pb-view.html +78 -40
- package/dist/demo/pb-view2.html +69 -46
- package/dist/demo/pb-view3.html +53 -48
- package/dist/demo/pb-view4.html +70 -49
- package/dist/demo/pb-zoom.html +2 -2
- package/dist/{es-global-bridge-d8ce175d.js → es-global-bridge-D8ZcUcx_.js} +0 -4
- package/dist/focus-mixin-VCsFap6b.js +768 -0
- package/dist/images/icons.svg +217 -0
- package/dist/jinn-codemirror-DETLdm08.js +1 -0
- package/dist/lib/openseadragon.min.js +80 -0
- package/dist/lib/openseadragon.min.js.map +1 -0
- package/dist/pb-code-editor.js +25 -20
- package/dist/pb-component-docs.js +414 -3225
- package/dist/pb-components-bundle.js +3046 -4402
- package/dist/pb-dialog-tklYGWfc.js +121 -0
- package/dist/pb-edit-app.js +208 -107
- package/dist/pb-elements.json +716 -249
- package/dist/pb-facsimile.js +46 -0
- package/dist/pb-i18n-C0NDma4h.js +1 -0
- package/dist/pb-leaflet-map.js +23 -23
- package/dist/pb-mei.js +152 -134
- package/dist/pb-mixin-DHoWQheB.js +1 -0
- package/dist/pb-odd-editor.js +1671 -1231
- package/dist/pb-tify.js +1 -27
- package/dist/unsafe-html-D5VGo9Oq.js +1 -0
- package/dist/urls-BEONu_g4.js +1 -0
- package/eslint.config.mjs +92 -0
- package/gh-pages.js +5 -3
- package/i18n/common/en.json +6 -0
- package/i18n/common/pl.json +2 -2
- package/images/icons.svg +217 -0
- package/index.html +0 -5
- package/lib/leaflet-src.js.map +1 -0
- package/lib/leaflet.markercluster-src.js.map +1 -0
- package/lib/openseadragon.min.js +6 -6
- package/package.json +56 -81
- package/pb-elements.json +716 -249
- package/rollup.config.mjs +312 -0
- package/src/assets/components.css +5 -5
- package/src/assets/design-system.css +607 -0
- package/src/authority/airtable.js +20 -21
- package/src/authority/anton.js +129 -129
- package/src/authority/custom.js +70 -27
- package/src/authority/geonames.js +38 -32
- package/src/authority/gnd.js +50 -42
- package/src/authority/kbga.js +136 -134
- package/src/authority/metagrid.js +44 -46
- package/src/authority/reconciliation.js +66 -68
- package/src/authority/registry.js +4 -4
- package/src/docs/demo-utils.js +91 -0
- package/src/docs/pb-component-docs.js +287 -147
- package/src/docs/pb-component-view.js +380 -273
- package/src/docs/pb-components-list.js +115 -51
- package/src/docs/pb-demo-snippet.js +199 -174
- package/src/dts-client.js +306 -303
- package/src/dts-select-endpoint.js +125 -85
- package/src/parse-date-service.js +184 -135
- package/src/pb-ajax.js +175 -173
- package/src/pb-authority-lookup.js +198 -158
- package/src/pb-autocomplete.js +731 -313
- package/src/pb-blacklab-highlight.js +266 -260
- package/src/pb-blacklab-results.js +230 -225
- package/src/pb-browse-docs.js +601 -484
- package/src/pb-browse.js +68 -65
- package/src/pb-clipboard.js +97 -76
- package/src/pb-code-editor.js +111 -103
- package/src/pb-code-highlight.js +234 -204
- package/src/pb-codepen.js +81 -73
- package/src/pb-collapse.js +265 -152
- package/src/pb-combo-box.js +191 -191
- package/src/pb-components-bundle.js +1 -7
- package/src/pb-components.js +2 -6
- package/src/pb-custom-form.js +230 -141
- package/src/pb-dialog.js +99 -63
- package/src/pb-document.js +118 -91
- package/src/pb-download.js +214 -198
- package/src/pb-drawer.js +146 -149
- package/src/pb-edit-app.js +471 -240
- package/src/pb-edit-xml.js +101 -98
- package/src/pb-events.js +126 -107
- package/src/pb-facs-link.js +130 -101
- package/src/pb-facsimile.js +494 -410
- package/src/pb-fetch.js +389 -0
- package/src/pb-formula.js +152 -154
- package/src/pb-geolocation.js +130 -132
- package/src/pb-grid-action.js +59 -56
- package/src/pb-grid.js +388 -228
- package/src/pb-highlight.js +142 -142
- package/src/pb-hotkeys.js +40 -42
- package/src/pb-i18n.js +115 -127
- package/src/pb-icon-button.js +108 -0
- package/src/pb-icon.js +283 -0
- package/src/pb-image-strip.js +85 -79
- package/src/pb-lang.js +142 -57
- package/src/pb-leaflet-map.js +551 -483
- package/src/pb-link.js +132 -126
- package/src/pb-load.js +495 -428
- package/src/pb-login.js +303 -248
- package/src/pb-manage-odds.js +384 -338
- package/src/pb-map-icon.js +90 -90
- package/src/pb-map-layer.js +86 -86
- package/src/pb-markdown.js +107 -110
- package/src/pb-media-query.js +75 -73
- package/src/pb-mei.js +523 -303
- package/src/pb-message.js +144 -98
- package/src/pb-mixin.js +268 -265
- package/src/pb-navigation.js +83 -96
- package/src/pb-observable.js +39 -39
- package/src/pb-odd-editor.js +1209 -948
- package/src/pb-odd-elementspec-editor.js +375 -310
- package/src/pb-odd-model-editor.js +1189 -941
- package/src/pb-odd-parameter-editor.js +269 -170
- package/src/pb-odd-rendition-editor.js +184 -131
- package/src/pb-page.js +451 -422
- package/src/pb-paginate.js +260 -178
- package/src/pb-panel.js +217 -183
- package/src/pb-popover-themes.js +16 -9
- package/src/pb-popover.js +297 -288
- package/src/pb-print-preview.js +128 -128
- package/src/pb-progress.js +52 -52
- package/src/pb-repeat.js +141 -108
- package/src/pb-restricted.js +85 -78
- package/src/pb-search.js +258 -230
- package/src/pb-select-feature.js +210 -126
- package/src/pb-select-odd.js +184 -118
- package/src/pb-select-template.js +113 -78
- package/src/pb-select.js +330 -229
- package/src/pb-split-list.js +181 -176
- package/src/pb-svg.js +81 -80
- package/src/pb-table-column.js +55 -55
- package/src/pb-table-grid.js +334 -205
- package/src/pb-tabs.js +238 -61
- package/src/pb-tify.js +3331 -126
- package/src/pb-timeline.js +394 -255
- package/src/pb-toggle-feature.js +196 -188
- package/src/pb-upload.js +201 -176
- package/src/pb-version.js +22 -34
- package/src/pb-view-annotate.js +138 -102
- package/src/pb-view.js +1722 -1272
- package/src/pb-zoom.js +144 -46
- package/src/search-result-service.js +256 -223
- package/src/seed-element.js +14 -22
- package/src/settings.js +4 -4
- package/src/theming.js +98 -91
- package/src/urls.js +403 -289
- package/src/utils.js +53 -51
- package/vite.config.js +86 -0
- package/css/pb-styles.css +0 -51
- package/dist/iron-form-3b8dcaa7.js +0 -210
- package/dist/jinn-codemirror-da0e2d1f.js +0 -1
- package/dist/paper-checkbox-515a5284.js +0 -1597
- package/dist/paper-icon-button-b1d31571.js +0 -398
- package/dist/paper-listbox-a3b7175c.js +0 -1265
- package/dist/pb-i18n-0611135a.js +0 -1
- package/dist/pb-mixin-b1caa22e.js +0 -158
- package/dist/polymer-hack.js +0 -1
- package/dist/vaadin-element-mixin-6e4cee3a.js +0 -527
- package/lib/Control.Geocoder.min.js +0 -2
- package/lib/Control.Geocoder.min.js.map +0 -1
- package/src/assets/pb-styles.css +0 -51
- package/src/pb-light-dom.js +0 -40
- package/src/polymer-hack.js +0 -6
package/src/pb-page.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { LitElement, html, css } from 'lit
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import i18next from 'i18next';
|
|
3
3
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
4
4
|
import XHR from 'i18next-xhr-backend';
|
|
5
5
|
import Backend from 'i18next-chained-backend';
|
|
6
6
|
import { pbMixin, clearPageEvents } from './pb-mixin.js';
|
|
7
7
|
import { resolveURL } from './utils.js';
|
|
8
|
-
import { loadStylesheets } from
|
|
9
|
-
import { initTranslation } from
|
|
10
|
-
import { typesetMath } from
|
|
11
|
-
import { registry } from
|
|
8
|
+
import { loadStylesheets } from './theming.js';
|
|
9
|
+
import { initTranslation } from './pb-i18n.js';
|
|
10
|
+
import { typesetMath } from './pb-formula.js';
|
|
11
|
+
import { registry } from './urls.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Make sure there's only one instance of pb-page active at any time.
|
|
@@ -20,7 +20,7 @@ let _instance;
|
|
|
20
20
|
* Among other things, this element determines the TEI Publisher
|
|
21
21
|
* instance to which all elements will talk (property `endpoint`), and
|
|
22
22
|
* initializes the i18n language module.
|
|
23
|
-
*
|
|
23
|
+
*
|
|
24
24
|
* @slot - default unnamed slot for content
|
|
25
25
|
* @fires pb-page-ready - fired when the endpoint and language settings have been determined
|
|
26
26
|
* @fires pb-i18n-update - fired when the user selected a different display language
|
|
@@ -28,446 +28,475 @@ let _instance;
|
|
|
28
28
|
* @fires pb-toggle - when received, dispatch state changes to the elements on the page (see `pb-toggle-feature`, `pb-select-feature`)
|
|
29
29
|
*/
|
|
30
30
|
export class PbPage extends pbMixin(LitElement) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
31
|
+
static get properties() {
|
|
32
|
+
return {
|
|
33
|
+
...super.properties,
|
|
34
|
+
/**
|
|
35
|
+
* TEI Publisher internal: set to the root URL of the current app
|
|
36
|
+
*/
|
|
37
|
+
appRoot: {
|
|
38
|
+
type: String,
|
|
39
|
+
attribute: 'app-root',
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Can be used to define parameters which should be serialized in the
|
|
43
|
+
* URL path rather than as query parameters. Expects a url pattern
|
|
44
|
+
* relative to the application root
|
|
45
|
+
* (supported patterns are documented in the
|
|
46
|
+
* [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) library documentation).
|
|
47
|
+
*
|
|
48
|
+
* For example, a pattern `:lang/texts/:path/:id?` would support URLs like
|
|
49
|
+
* `en/texts/text1/chapter1`. Whenever components change state – e.g. due to a navigation
|
|
50
|
+
* event – the standard parameters `path`, `lang` and `id` would be serialized into the
|
|
51
|
+
* URL path pattern rather than query parameters.
|
|
52
|
+
*/
|
|
53
|
+
urlTemplate: {
|
|
54
|
+
type: String,
|
|
55
|
+
attribute: 'url-template',
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* A comma-separated list of parameter names which should not be reflected on the browser URL.
|
|
59
|
+
* Use this to exclude e.g. the default `odd` parameter of a pb-view to be shown in the
|
|
60
|
+
* browser URL.
|
|
61
|
+
*/
|
|
62
|
+
urlIgnore: {
|
|
63
|
+
type: String,
|
|
64
|
+
attribute: 'url-ignore',
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Is the resource path part of the URL or should it be
|
|
68
|
+
* encoded as a parameter? TEI Publisher uses the
|
|
69
|
+
* URL path, but the webcomponent demos need to encode the resource path
|
|
70
|
+
* in a query parameter.
|
|
71
|
+
*/
|
|
72
|
+
urlPath: {
|
|
73
|
+
type: String,
|
|
74
|
+
attribute: 'url-path',
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* If enabled, a hash in the URL (e.g. documentation.xml#introduction) will
|
|
78
|
+
* be interpreted as an xml:id to navigate to when talking to the server.
|
|
79
|
+
*/
|
|
80
|
+
idHash: {
|
|
81
|
+
type: Boolean,
|
|
82
|
+
attribute: 'id-hash',
|
|
83
|
+
},
|
|
84
|
+
/**
|
|
85
|
+
* TEI Publisher internal: set to the current page template.
|
|
86
|
+
*/
|
|
87
|
+
template: {
|
|
88
|
+
type: String,
|
|
89
|
+
},
|
|
90
|
+
/**
|
|
91
|
+
* The base URL of the TEI Publisher instance. All nested elements will
|
|
92
|
+
* talk to this instance. By default it is set to the URL the
|
|
93
|
+
* page was loaded from.
|
|
94
|
+
*
|
|
95
|
+
* The endpoint can be overwritten by providing an HTTP request parameter
|
|
96
|
+
* `_target` with an URL.
|
|
97
|
+
*/
|
|
98
|
+
endpoint: {
|
|
99
|
+
type: String,
|
|
100
|
+
reflect: true,
|
|
101
|
+
},
|
|
102
|
+
apiVersion: {
|
|
103
|
+
type: String,
|
|
104
|
+
attribute: 'api-version',
|
|
105
|
+
reflect: true,
|
|
106
|
+
},
|
|
107
|
+
/**
|
|
108
|
+
* Optional URL pointing to a directory from which additional i18n
|
|
109
|
+
* language files will be loaded. The URL should contain placeholders
|
|
110
|
+
* for the language (`lng`) and the namespace (`ns`), e.g.
|
|
111
|
+
*
|
|
112
|
+
* `resources/i18n/{{ns}}_{{lng}}.json`
|
|
113
|
+
*
|
|
114
|
+
* or
|
|
115
|
+
*
|
|
116
|
+
* `resources/i18n/{{ns}}/{{lng}}.json`
|
|
117
|
+
*
|
|
118
|
+
* The latter assumes custom language files in a subdirectory, the first
|
|
119
|
+
* expects the namespace to be specified at the start of the file name.
|
|
120
|
+
*
|
|
121
|
+
* The default namespace for custom language files is assumed to be `app`,
|
|
122
|
+
* but you can define additional namespaces via `localeFallbackNS`.
|
|
123
|
+
*/
|
|
124
|
+
locales: {
|
|
125
|
+
type: String,
|
|
126
|
+
},
|
|
127
|
+
/**
|
|
128
|
+
* Optional list of whitespace separated namespaces which should be searched
|
|
129
|
+
* for translations. By default, only the namespace `common` is queried.
|
|
130
|
+
* If the `locales` property is specified, an additional namespace `app` is added.
|
|
131
|
+
* You can add more namespace here, e.g. `custom`, if you want to provide
|
|
132
|
+
* translations for custom apps or components.
|
|
133
|
+
*/
|
|
134
|
+
localeFallbackNs: {
|
|
135
|
+
type: String,
|
|
136
|
+
attribute: 'locale-fallback-ns',
|
|
137
|
+
},
|
|
138
|
+
/**
|
|
139
|
+
* Comma-separated list of languages supported. If the detected language
|
|
140
|
+
* is not in this list, fall back to the configured fallback language.
|
|
141
|
+
*/
|
|
142
|
+
supportedLanguages: {
|
|
143
|
+
type: Array,
|
|
144
|
+
attribute: 'supported-languages',
|
|
145
|
+
converter(value) {
|
|
146
|
+
return value.split(/\s*,\s*/);
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
/**
|
|
150
|
+
* The fallback language to use if the detected language is not supported.
|
|
151
|
+
* Defaults to 'en'.
|
|
152
|
+
*/
|
|
153
|
+
fallbackLanguage: {
|
|
154
|
+
type: String,
|
|
155
|
+
attribute: 'fallback-language',
|
|
156
|
+
},
|
|
157
|
+
/**
|
|
158
|
+
* Set a language for i18n (e.g. 'en' or 'de'). If not set, browser language
|
|
159
|
+
* detection will be used.
|
|
160
|
+
*/
|
|
161
|
+
language: {
|
|
162
|
+
type: String,
|
|
163
|
+
},
|
|
164
|
+
/**
|
|
165
|
+
* If set, the element will wait for a language being set by i18n before
|
|
166
|
+
* it sends a `pb-page-ready` event. Elements like `pb-view` will wait
|
|
167
|
+
* for this event before displaying content.
|
|
168
|
+
*
|
|
169
|
+
* Also, `pb-view` will pass the configured language to the server endpoint
|
|
170
|
+
* where it will be available to ODD processing models in variable
|
|
171
|
+
* `$parameters?language` and can thus be used to change output depending on
|
|
172
|
+
* the user interface language.
|
|
173
|
+
*
|
|
174
|
+
* If you would like `pb-view` to refresh automatically whenever the language
|
|
175
|
+
* setting changes, specify property `useLanguage` on the corresponding `pb-view`.
|
|
176
|
+
*/
|
|
177
|
+
requireLanguage: {
|
|
178
|
+
type: Boolean,
|
|
179
|
+
attribute: 'require-language',
|
|
180
|
+
},
|
|
181
|
+
/**
|
|
182
|
+
* Will be set while the component is loading and unset when
|
|
183
|
+
* it is fully loaded. Use to avoid flash of unstyled content
|
|
184
|
+
* via CSS: set `unresolved` on `pb-page` in the HTML and
|
|
185
|
+
* add a CSS rule like:
|
|
186
|
+
*
|
|
187
|
+
* ```css
|
|
188
|
+
* pb-page[unresolved] {
|
|
189
|
+
* display: none;
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
unresolved: {
|
|
194
|
+
type: Boolean,
|
|
195
|
+
reflect: true,
|
|
196
|
+
},
|
|
197
|
+
theme: {
|
|
198
|
+
type: String,
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
constructor() {
|
|
204
|
+
super();
|
|
205
|
+
this.unresolved = true;
|
|
206
|
+
this.endpoint = '.';
|
|
207
|
+
this.urlTemplate = null;
|
|
208
|
+
this.urlIgnore = null;
|
|
209
|
+
this.urlPath = 'path';
|
|
210
|
+
this.idHash = false;
|
|
211
|
+
this.apiVersion = undefined;
|
|
212
|
+
this.requireLanguage = false;
|
|
213
|
+
this.supportedLanguages = null;
|
|
214
|
+
this.fallbackLanguage = 'en';
|
|
215
|
+
this.theme = null;
|
|
216
|
+
this._localeFallbacks = [];
|
|
217
|
+
this._i18nInstance = null;
|
|
218
|
+
|
|
219
|
+
if (_instance) {
|
|
220
|
+
this.disabled = true;
|
|
221
|
+
} else {
|
|
222
|
+
_instance = this;
|
|
223
|
+
|
|
224
|
+
// clear global page events which might have been set by other pb-page instances.
|
|
225
|
+
// important while running the test suite.
|
|
226
|
+
clearPageEvents();
|
|
202
227
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
get localeFallbackNs() {
|
|
231
|
+
// Expose a space-separated view of the current fallback namespaces
|
|
232
|
+
return this._localeFallbacks && this._localeFallbacks.length
|
|
233
|
+
? this._localeFallbacks.join(' ')
|
|
234
|
+
: '';
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
set localeFallbackNs(value) {
|
|
238
|
+
// Replace (not append) to avoid uncontrolled growth when attribute re-applies
|
|
239
|
+
const next = (value || '')
|
|
240
|
+
.split(/\s+/)
|
|
241
|
+
.map(s => s.trim())
|
|
242
|
+
.filter(Boolean);
|
|
243
|
+
// Deduplicate while preserving order
|
|
244
|
+
const seen = new Set();
|
|
245
|
+
this._localeFallbacks = next.filter(ns => (seen.has(ns) ? false : (seen.add(ns), true)));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
disconnectedCallback() {
|
|
249
|
+
super.disconnectedCallback();
|
|
250
|
+
this._i18nInstance = null;
|
|
251
|
+
if (_instance === this) {
|
|
252
|
+
// clear to allow future instances
|
|
253
|
+
_instance = null;
|
|
229
254
|
}
|
|
255
|
+
}
|
|
230
256
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
257
|
+
async connectedCallback() {
|
|
258
|
+
super.connectedCallback();
|
|
234
259
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
this._i18nInstance = null;
|
|
238
|
-
if (_instance === this) {
|
|
239
|
-
// clear to allow future instances
|
|
240
|
-
_instance = null;
|
|
241
|
-
}
|
|
260
|
+
if (this.disabled) {
|
|
261
|
+
return;
|
|
242
262
|
}
|
|
243
263
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
registry.configure(this.urlPath === 'path', this.idHash, this.appRoot, this.urlTemplate, this.urlIgnore);
|
|
252
|
-
|
|
253
|
-
this.endpoint = this.endpoint.replace(/\/+$/, '');
|
|
254
|
-
|
|
255
|
-
if (this.locales && this._localeFallbacks.indexOf('app') === -1) {
|
|
256
|
-
this._localeFallbacks.push('app');
|
|
257
|
-
}
|
|
258
|
-
this._localeFallbacks.push('common');
|
|
259
|
-
|
|
260
|
-
const target = registry.state._target;
|
|
261
|
-
if (target) {
|
|
262
|
-
this.endpoint = target;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const apiVersion = registry.state._api;
|
|
266
|
-
if (apiVersion) {
|
|
267
|
-
this.apiVersion = apiVersion;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const stylesheetURLs = [
|
|
271
|
-
// TODO: replace with this.toAbsoluteURL
|
|
272
|
-
this.toAbsoluteURL('resources/css/components.css', this.endpoint)
|
|
273
|
-
];
|
|
274
|
-
if (this.theme) {
|
|
275
|
-
stylesheetURLs.push(this.toAbsoluteURL(this.theme, this.endpoint));
|
|
276
|
-
}
|
|
277
|
-
console.log('<pb-page> Loading component theme stylesheets from %s', stylesheetURLs.join(', '));
|
|
278
|
-
this._themeSheet = await loadStylesheets(stylesheetURLs);
|
|
279
|
-
|
|
280
|
-
// try to figure out what version of TEI Publisher the server is running
|
|
281
|
-
if (!this.apiVersion) {
|
|
282
|
-
// first check if it has a login endpoint, i.e. runs a version < 7
|
|
283
|
-
// this is necessary to prevent a CORS failure
|
|
284
|
-
const json = await fetch(`${this.endpoint}/login`)
|
|
285
|
-
.then((res) => {
|
|
286
|
-
if (res.ok) {
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
// if not, access the actual /api/version endpoint to retrieve the API version
|
|
290
|
-
return fetch(`${this.endpoint}/api/version`)
|
|
291
|
-
.then((res2) => res2.json());
|
|
292
|
-
})
|
|
293
|
-
.catch(() => fetch(`${this.endpoint}/api/version`)
|
|
294
|
-
.then((res2) => res2.json())
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
if (json) {
|
|
298
|
-
this.apiVersion = json.api;
|
|
299
|
-
console.log(`<pb-page> Server reports API version ${this.apiVersion} with app ${json.app.name}/${json.app.version} running on ${json.engine.name}/${json.engine.version}`);
|
|
300
|
-
} else {
|
|
301
|
-
console.log('<pb-page> No API version reported by server, assuming 0.9.0');
|
|
302
|
-
this.apiVersion = '0.9.0';
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (!this.requireLanguage) {
|
|
307
|
-
this.signalReady('pb-page-ready', {
|
|
308
|
-
endpoint: this.endpoint,
|
|
309
|
-
template: this.template,
|
|
310
|
-
apiVersion: this.apiVersion
|
|
311
|
-
});
|
|
312
|
-
} else if (this._i18nInstance) {
|
|
313
|
-
this.signalReady('pb-page-ready', {
|
|
314
|
-
endpoint: this.endpoint,
|
|
315
|
-
apiVersion: this.apiVersion,
|
|
316
|
-
template: this.template,
|
|
317
|
-
language: this._i18nInstance.language
|
|
318
|
-
});
|
|
319
|
-
}
|
|
264
|
+
// Ensure attribute-provided endpoint is honored even before first update
|
|
265
|
+
const attrEndpoint = this.getAttribute('endpoint');
|
|
266
|
+
if (attrEndpoint) {
|
|
267
|
+
this.endpoint = attrEndpoint;
|
|
320
268
|
}
|
|
321
269
|
|
|
322
|
-
|
|
323
|
-
|
|
270
|
+
registry.configure(
|
|
271
|
+
this.urlPath === 'path',
|
|
272
|
+
this.idHash,
|
|
273
|
+
this.appRoot,
|
|
274
|
+
this.urlTemplate,
|
|
275
|
+
this.urlIgnore,
|
|
276
|
+
);
|
|
324
277
|
|
|
325
|
-
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
278
|
+
this.endpoint = this.endpoint.replace(/\/+$/, '');
|
|
328
279
|
|
|
329
|
-
const slot = this.shadowRoot.querySelector('slot');
|
|
330
|
-
slot.addEventListener('slotchange', () => {
|
|
331
|
-
const ev = new CustomEvent('pb-page-loaded', {
|
|
332
|
-
bubbles: true,
|
|
333
|
-
composed: true
|
|
334
|
-
});
|
|
335
|
-
this.dispatchEvent(ev);
|
|
336
|
-
}, { once: true });
|
|
337
|
-
|
|
338
|
-
const defaultLocales = resolveURL('../i18n/') + '{{ns}}/{{lng}}.json';
|
|
339
|
-
console.log('<pb-page> Loading locales. common: %s; additional: %s; namespaces: %o',
|
|
340
|
-
defaultLocales, this.locales, this._localeFallbacks);
|
|
341
|
-
const backends = this.locales ? [XHR, XHR] : [XHR];
|
|
342
|
-
const backendOptions = [{
|
|
343
|
-
loadPath: defaultLocales,
|
|
344
|
-
crossDomain: true
|
|
345
|
-
}];
|
|
346
|
-
if (this.locales) {
|
|
347
|
-
backendOptions.unshift({
|
|
348
|
-
loadPath: this.locales,
|
|
349
|
-
crossDomain: true
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
const options = {
|
|
353
|
-
fallbackLng: this.fallbackLanguage,
|
|
354
|
-
defaultNS: 'common',
|
|
355
|
-
ns: ['common'],
|
|
356
|
-
debug: false,
|
|
357
|
-
load: 'languageOnly',
|
|
358
|
-
detection: {
|
|
359
|
-
lookupQuerystring: 'lang'
|
|
360
|
-
},
|
|
361
|
-
backend: {
|
|
362
|
-
backends,
|
|
363
|
-
backendOptions
|
|
364
|
-
}
|
|
365
|
-
};
|
|
366
|
-
if (this.language) {
|
|
367
|
-
options.lng = this.language;
|
|
368
|
-
}
|
|
369
|
-
console.log('supported langs: %o', this.supportedLanguages);
|
|
370
|
-
if (this.supportedLanguages) {
|
|
371
|
-
options.supportedLngs = this.supportedLanguages;
|
|
372
|
-
}
|
|
373
280
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
options.ns = fallbacks;
|
|
379
|
-
}
|
|
380
|
-
console.log('<pb-page> i18next options: %o', options);
|
|
381
|
-
this._i18nInstance = i18next.createInstance();
|
|
382
|
-
this._i18nInstance
|
|
383
|
-
.use(LanguageDetector)
|
|
384
|
-
.use(Backend);
|
|
385
|
-
this._i18nInstance.init(options)
|
|
386
|
-
.then((t) => {
|
|
387
|
-
initTranslation(t);
|
|
388
|
-
// initialized and ready to go!
|
|
389
|
-
this._updateI18n(t);
|
|
390
|
-
this.signalReady('pb-i18n-update', { t, language: this._i18nInstance.language });
|
|
391
|
-
if (this.requireLanguage && this.apiVersion) {
|
|
392
|
-
this.signalReady('pb-page-ready', {
|
|
393
|
-
endpoint: this.endpoint,
|
|
394
|
-
apiVersion: this.apiVersion,
|
|
395
|
-
template: this.template,
|
|
396
|
-
language: this._i18nInstance.language
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
});
|
|
281
|
+
const target = registry.state._target;
|
|
282
|
+
if (target) {
|
|
283
|
+
this.endpoint = target;
|
|
284
|
+
}
|
|
400
285
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
this.emitTo('pb-i18n-update', { t, language: this._i18nInstance.language }, []);
|
|
406
|
-
}, []);
|
|
407
|
-
});
|
|
286
|
+
const apiVersion = registry.state._api;
|
|
287
|
+
if (apiVersion) {
|
|
288
|
+
this.apiVersion = apiVersion;
|
|
289
|
+
}
|
|
408
290
|
|
|
291
|
+
const stylesheetURLs = [];
|
|
292
|
+
if (this.theme) {
|
|
293
|
+
stylesheetURLs.push(this.toAbsoluteURL(this.theme, this.endpoint));
|
|
294
|
+
} else {
|
|
295
|
+
stylesheetURLs.push('components.css');
|
|
296
|
+
}
|
|
297
|
+
console.log('<pb-page> Loading component theme stylesheets from %s', stylesheetURLs.join(', '));
|
|
298
|
+
this._themeSheet = await loadStylesheets(stylesheetURLs);
|
|
299
|
+
|
|
300
|
+
// try to figure out what version of TEI Publisher the server is running
|
|
301
|
+
if (!this.apiVersion) {
|
|
302
|
+
// first check if it has a login endpoint, i.e. runs a version < 7
|
|
303
|
+
// this is necessary to prevent a CORS failure
|
|
304
|
+
const json = await fetch(`${this.endpoint}/login`)
|
|
305
|
+
.then(res => {
|
|
306
|
+
if (res.ok) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
// if not, access the actual /api/version endpoint to retrieve the API version
|
|
310
|
+
return fetch(`${this.endpoint}/api/version`).then(res2 => res2.json());
|
|
311
|
+
})
|
|
312
|
+
.catch(() => fetch(`${this.endpoint}/api/version`).then(res2 => res2.json()));
|
|
313
|
+
|
|
314
|
+
if (json) {
|
|
315
|
+
this.apiVersion = json.api;
|
|
316
|
+
console.log(
|
|
317
|
+
`<pb-page> Server reports API version ${this.apiVersion} with app ${json.app.name}/${json.app.version} running on ${json.engine.name}/${json.engine.version}`,
|
|
318
|
+
);
|
|
319
|
+
} else {
|
|
320
|
+
console.log('<pb-page> No API version reported by server, assuming 0.9.0');
|
|
321
|
+
this.apiVersion = '0.9.0';
|
|
322
|
+
}
|
|
323
|
+
}
|
|
409
324
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
this.
|
|
325
|
+
if (!this.requireLanguage) {
|
|
326
|
+
this.signalReady('pb-page-ready', {
|
|
327
|
+
endpoint: this.endpoint,
|
|
328
|
+
template: this.template,
|
|
329
|
+
apiVersion: this.apiVersion,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
// Note: If requireLanguage is true, pb-page-ready will be signaled after i18n initialization in firstUpdated()
|
|
333
|
+
}
|
|
413
334
|
|
|
414
|
-
|
|
415
|
-
|
|
335
|
+
firstUpdated() {
|
|
336
|
+
super.firstUpdated();
|
|
416
337
|
|
|
417
|
-
|
|
338
|
+
if (this.disabled) {
|
|
339
|
+
return;
|
|
418
340
|
}
|
|
419
341
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
elem.setAttribute(m[1], translated);
|
|
429
|
-
} else {
|
|
430
|
-
elem.innerHTML = translated;
|
|
431
|
-
}
|
|
432
|
-
m = regex.exec(targets);
|
|
433
|
-
}
|
|
342
|
+
|
|
343
|
+
const slot = this.shadowRoot.querySelector('slot');
|
|
344
|
+
slot.addEventListener(
|
|
345
|
+
'slotchange',
|
|
346
|
+
() => {
|
|
347
|
+
const ev = new CustomEvent('pb-page-loaded', {
|
|
348
|
+
bubbles: true,
|
|
349
|
+
composed: true,
|
|
434
350
|
});
|
|
351
|
+
this.dispatchEvent(ev);
|
|
352
|
+
},
|
|
353
|
+
{ once: true },
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const defaultLocales = this.endpoint
|
|
357
|
+
? `${this.toAbsoluteURL('resources/i18n/', this.endpoint)}{{ns}}/{{lng}}.json`
|
|
358
|
+
: `${resolveURL('../i18n/')}{{ns}}/{{lng}}.json`;
|
|
359
|
+
console.log(
|
|
360
|
+
'<pb-page> Loading locales. common: %s; additional: %s; namespaces: %o',
|
|
361
|
+
defaultLocales,
|
|
362
|
+
this.locales,
|
|
363
|
+
this._localeFallbacks,
|
|
364
|
+
);
|
|
365
|
+
const backends = this.locales ? [XHR, XHR] : [XHR];
|
|
366
|
+
const backendOptions = [
|
|
367
|
+
{
|
|
368
|
+
loadPath: defaultLocales,
|
|
369
|
+
crossDomain: true,
|
|
370
|
+
},
|
|
371
|
+
];
|
|
372
|
+
if (this.locales) {
|
|
373
|
+
backendOptions.unshift({
|
|
374
|
+
loadPath: this.locales,
|
|
375
|
+
crossDomain: true,
|
|
376
|
+
});
|
|
435
377
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
378
|
+
const options = {
|
|
379
|
+
fallbackLng: this.fallbackLanguage,
|
|
380
|
+
defaultNS: 'common',
|
|
381
|
+
ns: ['common'],
|
|
382
|
+
debug: false,
|
|
383
|
+
load: 'languageOnly',
|
|
384
|
+
detection: {
|
|
385
|
+
lookupQuerystring: 'lang',
|
|
386
|
+
},
|
|
387
|
+
backend: {
|
|
388
|
+
backends,
|
|
389
|
+
backendOptions,
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
if (this.language) {
|
|
393
|
+
options.lng = this.language;
|
|
439
394
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
* and dispatch actions to the elements on the page.
|
|
444
|
-
*/
|
|
445
|
-
_toggleFeatures(ev) {
|
|
446
|
-
const sc = ev.detail;
|
|
447
|
-
this.querySelectorAll(sc.selector).forEach(node => {
|
|
448
|
-
const command = sc.command || 'toggle';
|
|
449
|
-
if (node.command) {
|
|
450
|
-
node.command(command, sc.state);
|
|
451
|
-
}
|
|
452
|
-
if (sc.state) {
|
|
453
|
-
node.classList.add(command);
|
|
454
|
-
} else {
|
|
455
|
-
node.classList.remove(command);
|
|
456
|
-
}
|
|
457
|
-
});
|
|
395
|
+
console.log('supported langs: %o', this.supportedLanguages);
|
|
396
|
+
if (this.supportedLanguages) {
|
|
397
|
+
options.supportedLngs = this.supportedLanguages;
|
|
458
398
|
}
|
|
459
399
|
|
|
460
|
-
|
|
461
|
-
|
|
400
|
+
if (this._localeFallbacks.length > 0) {
|
|
401
|
+
const fallbacks = this._localeFallbacks.slice();
|
|
402
|
+
options.defaultNS = fallbacks[0];
|
|
403
|
+
options.fallbackNS = fallbacks.slice(1);
|
|
404
|
+
options.ns = fallbacks;
|
|
462
405
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
406
|
+
console.log('<pb-page> i18next options: %o', options);
|
|
407
|
+
this._i18nInstance = i18next.createInstance();
|
|
408
|
+
this._i18nInstance.use(LanguageDetector).use(Backend);
|
|
409
|
+
this._i18nInstance.init(options).then(t => {
|
|
410
|
+
initTranslation(t);
|
|
411
|
+
// initialized and ready to go!
|
|
412
|
+
this._updateI18n(t);
|
|
413
|
+
this.signalReady('pb-i18n-update', { t, language: this._i18nInstance?.language });
|
|
414
|
+
if (this.requireLanguage) {
|
|
415
|
+
this.signalReady('pb-page-ready', {
|
|
416
|
+
endpoint: this.endpoint,
|
|
417
|
+
apiVersion: this.apiVersion,
|
|
418
|
+
template: this.template,
|
|
419
|
+
language: this._i18nInstance?.language,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// React to language change events by updating i18n and notifying listeners
|
|
425
|
+
this.subscribeTo('pb-i18n-language', ev => {
|
|
426
|
+
const { language } = ev.detail;
|
|
427
|
+
this._i18nInstance.changeLanguage(language).then(t => {
|
|
428
|
+
this._updateI18n(t);
|
|
429
|
+
this.emitTo('pb-i18n-update', { t, language: this._i18nInstance?.language }, []);
|
|
430
|
+
}, []);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// this.subscribeTo('pb-global-toggle', this._toggleFeatures.bind(this));
|
|
434
|
+
this.addEventListener('pb-global-toggle', this._toggleFeatures.bind(this));
|
|
435
|
+
// Avoid a Lit reactive update here; just remove the attribute instead.
|
|
436
|
+
this.removeAttribute('unresolved');
|
|
437
|
+
|
|
438
|
+
console.log('<pb-page> endpoint: %s; trigger window resize', this.endpoint);
|
|
439
|
+
// Guard: some app-header implementations may not expose _notifyLayoutChanged
|
|
440
|
+
this.querySelectorAll('app-header').forEach(h => {
|
|
441
|
+
if (typeof h._notifyLayoutChanged === 'function') {
|
|
442
|
+
h._notifyLayoutChanged();
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
typesetMath(this);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
_updateI18n(t) {
|
|
450
|
+
this.querySelectorAll('[data-i18n]').forEach(elem => {
|
|
451
|
+
const targets = elem.getAttribute('data-i18n');
|
|
452
|
+
const regex = /(?:\[([^\]]+)\])?([^;]+)/g;
|
|
453
|
+
let m = regex.exec(targets);
|
|
454
|
+
while (m) {
|
|
455
|
+
const translated = t(m[2]);
|
|
456
|
+
if (m[1]) {
|
|
457
|
+
elem.setAttribute(m[1], translated);
|
|
458
|
+
} else {
|
|
459
|
+
elem.innerHTML = translated;
|
|
468
460
|
}
|
|
469
|
-
|
|
470
|
-
|
|
461
|
+
m = regex.exec(targets);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
get stylesheet() {
|
|
467
|
+
return this._themeSheet;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Handle the `pb-toggle` event sent by `pb-select-feature` or `pb-toggle-feature`
|
|
472
|
+
* and dispatch actions to the elements on the page.
|
|
473
|
+
*/
|
|
474
|
+
_toggleFeatures(ev) {
|
|
475
|
+
const sc = ev.detail;
|
|
476
|
+
this.querySelectorAll(sc.selector).forEach(node => {
|
|
477
|
+
const command = sc.command || 'toggle';
|
|
478
|
+
if (node.command) {
|
|
479
|
+
node.command(command, sc.state);
|
|
480
|
+
}
|
|
481
|
+
if (sc.state) {
|
|
482
|
+
node.classList.add(command);
|
|
483
|
+
} else {
|
|
484
|
+
node.classList.remove(command);
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
render() {
|
|
490
|
+
return html`<slot></slot>`;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
static get styles() {
|
|
494
|
+
return css`
|
|
495
|
+
:host {
|
|
496
|
+
display: block;
|
|
497
|
+
}
|
|
498
|
+
`;
|
|
499
|
+
}
|
|
471
500
|
}
|
|
472
501
|
|
|
473
|
-
customElements.define('pb-page', PbPage);
|
|
502
|
+
customElements.define('pb-page', PbPage);
|