@jsenv/plugin-toolbar 1.4.14 → 1.4.16

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.
@@ -26,10 +26,16 @@ const injectToolbar = async ({
26
26
  close: closeToolbar
27
27
  };
28
28
  if (document.readyState !== "complete") {
29
+ if (logLevel === "debug") {
30
+ console.debug('toolbar injection: wait for window "load"');
31
+ }
29
32
  await new Promise(resolve => {
30
33
  window.addEventListener("load", resolve);
31
34
  });
32
35
  }
36
+ if (logLevel === "debug") {
37
+ console.debug("toolbar injection: wait idleCallback");
38
+ }
33
39
  await new Promise(resolve => {
34
40
  if (window.requestIdleCallback) {
35
41
  window.requestIdleCallback(resolve, {
@@ -40,10 +46,15 @@ const injectToolbar = async ({
40
46
  }
41
47
  });
42
48
  const jsenvToolbar = document.createElement("jsenv-toolbar");
49
+ console.debug("toolbar injection: create iframe");
43
50
  iframe = createIframeNode();
44
51
  const toolbarTriggerNode = createToolbarTriggerNode();
45
- jsenvToolbar.appendChild(iframe);
46
- jsenvToolbar.appendChild(toolbarTriggerNode);
52
+ appendIntoRespectingLineBreaksAndIndentation(iframe, jsenvToolbar, {
53
+ indent: 3
54
+ });
55
+ appendIntoRespectingLineBreaksAndIndentation(toolbarTriggerNode, jsenvToolbar, {
56
+ indent: 3
57
+ });
47
58
  const iframeLoadedPromise = iframeToLoadedPromise(iframe);
48
59
  const toolbarUrlObject = new URL(toolbarUrl, window.location.href);
49
60
  toolbarUrlObject.searchParams.set("logLevel", logLevel);
@@ -96,6 +107,7 @@ const injectToolbar = async ({
96
107
  const collapseToolbarTrigger = () => {
97
108
  toolbarTriggerNode.removeAttribute("data-expanded", "");
98
109
  };
110
+ console.debug("toolbar injection: inject iframe in document");
99
111
  const placeholder = getToolbarPlaceholder();
100
112
  placeholder.parentNode.replaceChild(jsenvToolbar, placeholder);
101
113
  const listenToolbarStateChange = callback => {
@@ -126,8 +138,10 @@ const injectToolbar = async ({
126
138
  });
127
139
  });
128
140
  await iframeLoadedPromise;
141
+ console.debug("toolbar injection: iframe loaded");
129
142
  resolveToolbarReadyPromise();
130
- iframe.removeAttribute("tabindex");
143
+ iframe.removeAttribute("tabindex"); // why so late? and not when creating the iframe?
144
+
131
145
  return iframe;
132
146
  };
133
147
  const createIframeNode = () => {
@@ -151,11 +165,42 @@ const createIframeNode = () => {
151
165
  });
152
166
  return iframe;
153
167
  };
168
+ const appendIntoRespectingLineBreaksAndIndentation = (node, parentNode, {
169
+ indent = 2
170
+ } = {}) => {
171
+ const indentMinusOne = " ".repeat(indent - 1);
172
+ const desiredIndent = " ".repeat(indent);
173
+ const previousSibling = parentNode.childNodes[parentNode.childNodes.length - 1];
174
+ if (previousSibling && previousSibling.nodeName === "#text") {
175
+ if (previousSibling.nodeValue === "\n".concat(indentMinusOne)) {
176
+ previousSibling.nodeValue = "\n".concat(desiredIndent);
177
+ }
178
+ if (previousSibling.nodeValue !== "\n".concat(desiredIndent)) {
179
+ previousSibling.nodeValue = "\n".concat(desiredIndent);
180
+ }
181
+ } else {
182
+ parentNode.appendChild(document.createTextNode("\n".concat(desiredIndent)));
183
+ }
184
+ parentNode.appendChild(node);
185
+ parentNode.appendChild(document.createTextNode("\n".concat(indentMinusOne)));
186
+ };
154
187
  const createToolbarTriggerNode = () => {
155
- const div = document.createElement("div");
156
- div.innerHTML = "\n<div id=\"jsenv_toolbar_trigger\" style=\"display:none\">\n <svg id=\"jsenv_toolbar_trigger_icon\">\n <use xlink:href=\"".concat(jsenvLogoSvgUrl, "#jsenv_logo\"></use>\n </svg>\n <style>\n #jsenv_toolbar_trigger {\n display: block;\n overflow: hidden;\n position: fixed;\n z-index: 1000;\n bottom: -32px;\n right: 20px;\n height: 40px;\n width: 40px;\n padding: 0;\n margin: 0;\n border-radius: 5px 5px 0 0;\n border: 1px solid rgba(0, 0, 0, 0.33);\n border-bottom: none;\n box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.46);\n background: transparent;\n text-align: center;\n transition: 600ms;\n }\n\n #jsenv_toolbar_trigger:hover {\n cursor: pointer;\n }\n\n #jsenv_toolbar_trigger[data-expanded] {\n bottom: 0;\n }\n\n #jsenv_toolbar_trigger_icon {\n width: 35px;\n height: 35px;\n opacity: 0;\n transition: 600ms;\n }\n\n #jsenv_toolbar_trigger[data-expanded] #jsenv_toolbar_trigger_icon {\n opacity: 1;\n }\n </style>\n</div>");
157
- const toolbarTrigger = div.firstElementChild;
158
- return toolbarTrigger;
188
+ const css = /* css */"\n #jsenv_toolbar_trigger {\n display: block;\n overflow: hidden;\n position: fixed;\n z-index: 1000;\n bottom: -32px;\n right: 20px;\n height: 40px;\n width: 40px;\n padding: 0;\n margin: 0;\n border-radius: 5px 5px 0 0;\n border: 1px solid rgba(0, 0, 0, 0.33);\n border-bottom: none;\n box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.46);\n background: transparent;\n text-align: center;\n transition: 600ms;\n }\n\n #jsenv_toolbar_trigger:hover {\n cursor: pointer;\n }\n\n #jsenv_toolbar_trigger[data-expanded] {\n bottom: 0;\n }\n\n #jsenv_toolbar_trigger_icon {\n width: 35px;\n height: 35px;\n opacity: 0;\n transition: 600ms;\n }\n\n #jsenv_toolbar_trigger[data-expanded] #jsenv_toolbar_trigger_icon {\n opacity: 1;\n }";
189
+ const html = /* html */" <div id=\"jsenv_toolbar_trigger\" style=\"display:none\">\n <style>".concat(css, "</style>\n <svg id=\"jsenv_toolbar_trigger_icon\">\n <use xlink:href=\"").concat(jsenvLogoSvgUrl, "#jsenv_logo\"></use>\n </svg>\n </div>");
190
+ class JsenvToolbarTriggerHtmlElement extends HTMLElement {
191
+ constructor() {
192
+ super();
193
+ const root = this.attachShadow({
194
+ mode: "open"
195
+ });
196
+ root.innerHTML = html;
197
+ }
198
+ }
199
+ if (customElements && !customElements.get("jsenv-toolbar-trigger")) {
200
+ customElements.define("jsenv-toolbar-trigger", JsenvToolbarTriggerHtmlElement);
201
+ }
202
+ const jsenvToolbarTriggerElement = new JsenvToolbarTriggerHtmlElement();
203
+ return jsenvToolbarTriggerElement;
159
204
  };
160
205
  const addToolbarEventCallback = (iframe, eventName, callback) => {
161
206
  const messageEventCallback = messageEvent => {
@@ -206,7 +251,7 @@ const queryPlaceholder = () => {
206
251
  };
207
252
  const createTooolbarPlaceholder = () => {
208
253
  const jsenvToolbar = document.createElement("jsenv-toolbar");
209
- document.body.appendChild(jsenvToolbar);
254
+ appendIntoRespectingLineBreaksAndIndentation(jsenvToolbar, document.body);
210
255
  return jsenvToolbar;
211
256
  };
212
257
  const iframeToLoadedPromise = iframe => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/plugin-toolbar",
3
- "version": "1.4.14",
3
+ "version": "1.4.16",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,10 +28,16 @@ export const injectToolbar = async ({
28
28
  };
29
29
 
30
30
  if (document.readyState !== "complete") {
31
+ if (logLevel === "debug") {
32
+ console.debug('toolbar injection: wait for window "load"');
33
+ }
31
34
  await new Promise((resolve) => {
32
35
  window.addEventListener("load", resolve);
33
36
  });
34
37
  }
38
+ if (logLevel === "debug") {
39
+ console.debug("toolbar injection: wait idleCallback");
40
+ }
35
41
  await new Promise((resolve) => {
36
42
  if (window.requestIdleCallback) {
37
43
  window.requestIdleCallback(resolve, { timeout: 400 });
@@ -40,10 +46,19 @@ export const injectToolbar = async ({
40
46
  }
41
47
  });
42
48
  const jsenvToolbar = document.createElement("jsenv-toolbar");
49
+ console.debug("toolbar injection: create iframe");
43
50
  iframe = createIframeNode();
44
51
  const toolbarTriggerNode = createToolbarTriggerNode();
45
- jsenvToolbar.appendChild(iframe);
46
- jsenvToolbar.appendChild(toolbarTriggerNode);
52
+ appendIntoRespectingLineBreaksAndIndentation(iframe, jsenvToolbar, {
53
+ indent: 3,
54
+ });
55
+ appendIntoRespectingLineBreaksAndIndentation(
56
+ toolbarTriggerNode,
57
+ jsenvToolbar,
58
+ {
59
+ indent: 3,
60
+ },
61
+ );
47
62
  const iframeLoadedPromise = iframeToLoadedPromise(iframe);
48
63
  const toolbarUrlObject = new URL(toolbarUrl, window.location.href);
49
64
  toolbarUrlObject.searchParams.set("logLevel", logLevel);
@@ -102,6 +117,7 @@ export const injectToolbar = async ({
102
117
  toolbarTriggerNode.removeAttribute("data-expanded", "");
103
118
  };
104
119
 
120
+ console.debug("toolbar injection: inject iframe in document");
105
121
  const placeholder = getToolbarPlaceholder();
106
122
  placeholder.parentNode.replaceChild(jsenvToolbar, placeholder);
107
123
 
@@ -136,8 +152,9 @@ export const injectToolbar = async ({
136
152
  );
137
153
 
138
154
  await iframeLoadedPromise;
155
+ console.debug("toolbar injection: iframe loaded");
139
156
  resolveToolbarReadyPromise();
140
- iframe.removeAttribute("tabindex");
157
+ iframe.removeAttribute("tabindex"); // why so late? and not when creating the iframe?
141
158
 
142
159
  return iframe;
143
160
  };
@@ -164,14 +181,31 @@ const createIframeNode = () => {
164
181
  return iframe;
165
182
  };
166
183
 
184
+ const appendIntoRespectingLineBreaksAndIndentation = (
185
+ node,
186
+ parentNode,
187
+ { indent = 2 } = {},
188
+ ) => {
189
+ const indentMinusOne = " ".repeat(indent - 1);
190
+ const desiredIndent = " ".repeat(indent);
191
+ const previousSibling =
192
+ parentNode.childNodes[parentNode.childNodes.length - 1];
193
+ if (previousSibling && previousSibling.nodeName === "#text") {
194
+ if (previousSibling.nodeValue === `\n${indentMinusOne}`) {
195
+ previousSibling.nodeValue = `\n${desiredIndent}`;
196
+ }
197
+ if (previousSibling.nodeValue !== `\n${desiredIndent}`) {
198
+ previousSibling.nodeValue = `\n${desiredIndent}`;
199
+ }
200
+ } else {
201
+ parentNode.appendChild(document.createTextNode(`\n${desiredIndent}`));
202
+ }
203
+ parentNode.appendChild(node);
204
+ parentNode.appendChild(document.createTextNode(`\n${indentMinusOne}`));
205
+ };
206
+
167
207
  const createToolbarTriggerNode = () => {
168
- const div = document.createElement("div");
169
- div.innerHTML = `
170
- <div id="jsenv_toolbar_trigger" style="display:none">
171
- <svg id="jsenv_toolbar_trigger_icon">
172
- <use xlink:href="${jsenvLogoSvgUrl}#jsenv_logo"></use>
173
- </svg>
174
- <style>
208
+ const css = /* css */ `
175
209
  #jsenv_toolbar_trigger {
176
210
  display: block;
177
211
  overflow: hidden;
@@ -209,11 +243,29 @@ const createToolbarTriggerNode = () => {
209
243
 
210
244
  #jsenv_toolbar_trigger[data-expanded] #jsenv_toolbar_trigger_icon {
211
245
  opacity: 1;
246
+ }`;
247
+ const html = /* html */ ` <div id="jsenv_toolbar_trigger" style="display:none">
248
+ <style>${css}</style>
249
+ <svg id="jsenv_toolbar_trigger_icon">
250
+ <use xlink:href="${jsenvLogoSvgUrl}#jsenv_logo"></use>
251
+ </svg>
252
+ </div>`;
253
+
254
+ class JsenvToolbarTriggerHtmlElement extends HTMLElement {
255
+ constructor() {
256
+ super();
257
+ const root = this.attachShadow({ mode: "open" });
258
+ root.innerHTML = html;
212
259
  }
213
- </style>
214
- </div>`;
215
- const toolbarTrigger = div.firstElementChild;
216
- return toolbarTrigger;
260
+ }
261
+ if (customElements && !customElements.get("jsenv-toolbar-trigger")) {
262
+ customElements.define(
263
+ "jsenv-toolbar-trigger",
264
+ JsenvToolbarTriggerHtmlElement,
265
+ );
266
+ }
267
+ const jsenvToolbarTriggerElement = new JsenvToolbarTriggerHtmlElement();
268
+ return jsenvToolbarTriggerElement;
217
269
  };
218
270
 
219
271
  const addToolbarEventCallback = (iframe, eventName, callback) => {
@@ -270,7 +322,7 @@ const queryPlaceholder = () => {
270
322
 
271
323
  const createTooolbarPlaceholder = () => {
272
324
  const jsenvToolbar = document.createElement("jsenv-toolbar");
273
- document.body.appendChild(jsenvToolbar);
325
+ appendIntoRespectingLineBreaksAndIndentation(jsenvToolbar, document.body);
274
326
  return jsenvToolbar;
275
327
  };
276
328