@schukai/monster 4.38.7 → 4.38.8

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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.38.8] - 2025-08-13
6
+
7
+ ### Bug Fixes
8
+
9
+ - handle message base64
10
+
11
+
12
+
5
13
  ## [4.38.7] - 2025-08-07
6
14
 
7
15
  ### Bug Fixes
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.3","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.38.7"}
1
+ {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.3","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.38.8"}
@@ -379,8 +379,22 @@ class MessageContent extends CustomElement {
379
379
 
380
380
  if (part.content && part.filename && part.contentType) {
381
381
  try {
382
- // Assuming part.content is base64 encoded. Adjust if your content is raw binary.
383
- const decodedContent = atob(part.content);
382
+ let content = part.content || "";
383
+ const contentTransferEncoding = (
384
+ part?.contentTransferEncoding || ""
385
+ ).toLowerCase();
386
+ switch (contentTransferEncoding) {
387
+ case "base64":
388
+ content = atob(content);
389
+
390
+ case "quoted-printable":
391
+ content = decodeQuotedPrintable(content);
392
+ break;
393
+
394
+ default:
395
+ }
396
+
397
+ const decodedContent = content;
384
398
  const uint8Array = new Uint8Array(decodedContent.length);
385
399
  for (let i = 0; i < decodedContent.length; i++) {
386
400
  uint8Array[i] = decodedContent.charCodeAt(i);
@@ -714,6 +728,19 @@ function getTranslations() {
714
728
  }
715
729
  }
716
730
 
731
+ function decodeQuotedPrintable(input) {
732
+ // Soft line breaks (= am Zeilenende) entfernen
733
+ let str = input.replace(/=\r?\n/g, "");
734
+
735
+ // =XX in das entsprechende Byte umwandeln
736
+ const bytes = str.replace(/=([A-Fa-f0-9]{2})/g, (_, hex) =>
737
+ String.fromCharCode(parseInt(hex, 16)),
738
+ );
739
+
740
+ // Als UTF-8 interpretieren
741
+ return decodeURIComponent(escape(bytes));
742
+ }
743
+
717
744
  /**
718
745
  * @private
719
746
  * @param index
@@ -726,15 +753,20 @@ function downloadAttachmentByIndex(index, attachments) {
726
753
  return;
727
754
  }
728
755
 
729
- const { filename, contentType, content } = part;
756
+ const { filename, contentType, content, contentTransferEncoding } = part;
730
757
 
731
758
  try {
732
759
  let decodedContent;
733
- if (contentType.startsWith("text/")) {
734
- // Check if it's a text type
735
- decodedContent = content; // Content is plain text
736
- } else {
737
- decodedContent = atob(content); // Assume base64 for other types
760
+ if (
761
+ contentTransferEncoding &&
762
+ contentTransferEncoding.toLowerCase() === "base64"
763
+ ) {
764
+ decodedContent = atob(content);
765
+ } else if (
766
+ contentTransferEncoding &&
767
+ contentTransferEncoding.toLowerCase() === "quoted-printable"
768
+ ) {
769
+ decodedContent = decodeQuotedPrintable(content);
738
770
  }
739
771
 
740
772
  const len = decodedContent.length;
@@ -16,9 +16,9 @@ import { Datasource, dataSourceSymbol } from "../datasource.mjs";
16
16
  import { DatasourceStyleSheet } from "../stylesheet/datasource.mjs";
17
17
  import { instanceSymbol } from "../../../constants.mjs";
18
18
  import {
19
- assembleMethodSymbol,
20
- registerCustomElement,
21
- getSlottedElements,
19
+ assembleMethodSymbol,
20
+ registerCustomElement,
21
+ getSlottedElements,
22
22
  } from "../../../dom/customelement.mjs";
23
23
  import { isArray } from "../../../types/is.mjs";
24
24
 
@@ -37,174 +37,174 @@ const dataChangeEventHandlerSymbol = Symbol("dataChangeEventHandler");
37
37
  * @summary A dom datasource
38
38
  */
39
39
  class Dom extends Datasource {
40
- /**
41
- * This method is called by the `instanceof` operator.
42
- * @return {symbol}
43
- */
44
- static get [instanceSymbol]() {
45
- return Symbol.for("@schukai/monster/components/datasource/dom@@instance");
46
- }
47
-
48
- /**
49
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
50
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
51
- *
52
- * The individual configuration values can be found in the table.
53
- *
54
- * @property {Object} templates Template definitions
55
- * @property {string} templates.main Main template
56
- * @property {Object} features Feature definitions
57
- * @property {boolean} features.autoInit Automatically initializes the component
58
- */
59
- get defaults() {
60
- return Object.assign({}, super.defaults, {
61
- templates: {
62
- main: getTemplate(),
63
- },
64
-
65
- features: {
66
- autoInit: true,
67
- },
68
-
69
- /** @private */
70
- sys: {
71
- pagination: {
72
- pages: 1,
73
- objectsPerPage: 10,
74
- currentPage: 1,
75
- },
76
- },
77
- });
78
- }
79
-
80
- /**
81
- * @return {void}
82
- */
83
- [assembleMethodSymbol]() {
84
- super[assembleMethodSymbol]();
85
- initEventHandler.call(this);
86
- updateDataSource.call(this);
87
- }
88
-
89
- /**
90
- * This method set the current page of the pagination
91
- *
92
- * @param {string} page
93
- * @return {Dom}
94
- */
95
- setParameters({ page }) {
96
- this.setOption("sys.pagination.currentPage", page);
97
- return this;
98
- }
99
-
100
- /**
101
- *
102
- * @return {CSSStyleSheet[]}
103
- */
104
- static getCSSStyleSheet() {
105
- return [DatasourceStyleSheet];
106
- }
107
-
108
- /**
109
- * @private
110
- * @return {string}
111
- */
112
- static getTag() {
113
- return "monster-datasource-dom";
114
- }
115
-
116
- /**
117
- * Reloads the data
118
- * @return {Promise<never>|*}
119
- */
120
- reload() {}
121
-
122
- /**
123
- * @return {void}
124
- */
125
- connectedCallback() {
126
- super.connectedCallback();
127
-
128
- if (this.getOption("features.autoInit")) {
129
- updateDataSource.call(this);
130
- }
131
- }
132
-
133
- /**
134
- * @return {int}
135
- */
136
- currentPage() {
137
- return this.getOption("sys.pagination.currentPage");
138
- }
40
+ /**
41
+ * This method is called by the `instanceof` operator.
42
+ * @return {symbol}
43
+ */
44
+ static get [instanceSymbol]() {
45
+ return Symbol.for("@schukai/monster/components/datasource/dom@@instance");
46
+ }
47
+
48
+ /**
49
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
50
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
51
+ *
52
+ * The individual configuration values can be found in the table.
53
+ *
54
+ * @property {Object} templates Template definitions
55
+ * @property {string} templates.main Main template
56
+ * @property {Object} features Feature definitions
57
+ * @property {boolean} features.autoInit Automatically initializes the component
58
+ */
59
+ get defaults() {
60
+ return Object.assign({}, super.defaults, {
61
+ templates: {
62
+ main: getTemplate(),
63
+ },
64
+
65
+ features: {
66
+ autoInit: true,
67
+ },
68
+
69
+ /** @private */
70
+ sys: {
71
+ pagination: {
72
+ pages: 1,
73
+ objectsPerPage: 10,
74
+ currentPage: 1,
75
+ },
76
+ },
77
+ });
78
+ }
79
+
80
+ /**
81
+ * @return {void}
82
+ */
83
+ [assembleMethodSymbol]() {
84
+ super[assembleMethodSymbol]();
85
+ initEventHandler.call(this);
86
+ updateDataSource.call(this);
87
+ }
88
+
89
+ /**
90
+ * This method set the current page of the pagination
91
+ *
92
+ * @param {string} page
93
+ * @return {Dom}
94
+ */
95
+ setParameters({ page }) {
96
+ this.setOption("sys.pagination.currentPage", page);
97
+ return this;
98
+ }
99
+
100
+ /**
101
+ *
102
+ * @return {CSSStyleSheet[]}
103
+ */
104
+ static getCSSStyleSheet() {
105
+ return [DatasourceStyleSheet];
106
+ }
107
+
108
+ /**
109
+ * @private
110
+ * @return {string}
111
+ */
112
+ static getTag() {
113
+ return "monster-datasource-dom";
114
+ }
115
+
116
+ /**
117
+ * Reloads the data
118
+ * @return {Promise<never>|*}
119
+ */
120
+ reload() {}
121
+
122
+ /**
123
+ * @return {void}
124
+ */
125
+ connectedCallback() {
126
+ super.connectedCallback();
127
+
128
+ if (this.getOption("features.autoInit")) {
129
+ updateDataSource.call(this);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * @return {int}
135
+ */
136
+ currentPage() {
137
+ return this.getOption("sys.pagination.currentPage");
138
+ }
139
139
  }
140
140
 
141
141
  /**
142
142
  * @private
143
143
  */
144
144
  function initEventHandler() {
145
- /**
146
- * @param {Event} event
147
- */
148
- this[dataChangeEventHandlerSymbol] = (event) => {
149
- updateDataSource.call(this);
150
- };
151
-
152
- new MutationObserver(this[dataChangeEventHandlerSymbol]).observe(this, {
153
- childList: true,
154
- subtree: true,
155
- characterData: true,
156
- });
145
+ /**
146
+ * @param {Event} event
147
+ */
148
+ this[dataChangeEventHandlerSymbol] = (event) => {
149
+ updateDataSource.call(this);
150
+ };
151
+
152
+ new MutationObserver(this[dataChangeEventHandlerSymbol]).observe(this, {
153
+ childList: true,
154
+ subtree: true,
155
+ characterData: true,
156
+ });
157
157
  }
158
158
 
159
159
  /**
160
160
  * @private
161
161
  */
162
162
  function updateDataSource() {
163
- let data = null;
164
- getSlottedElements.call(this).forEach((element) => {
165
- if (!(element instanceof HTMLScriptElement)) {
166
- return;
167
- }
168
- if (element.type !== "application/json") {
169
- return;
170
- }
171
-
172
- const d = JSON.parse(element.textContent);
173
- if (data === null) {
174
- if (isArray(d)) {
175
- data = [];
176
- } else {
177
- data = {};
178
- }
179
- }
180
-
181
- if (isArray(data) && !isArray(d)) {
182
- throw new Error("Type mismatch");
183
- }
184
-
185
- if (!isArray(data) && isArray(d)) {
186
- throw new Error("Type mismatch");
187
- }
188
-
189
- if (isArray(data)) {
190
- data.push(...d);
191
- return;
192
- }
193
-
194
- data = Object.assign({}, d);
195
- });
196
-
197
- if (data === null) {
198
- data = [];
199
- }
200
-
201
- // set pagination
202
- this.setOption("sys.pagination.objectsPerPage", 1);
203
- this.setOption("sys.pagination.pages", data.length);
204
- this.setOption("sys.pagination.currentPage", 1);
205
-
206
- /** call setter */
207
- this.data = data;
163
+ let data = null;
164
+ getSlottedElements.call(this).forEach((element) => {
165
+ if (!(element instanceof HTMLScriptElement)) {
166
+ return;
167
+ }
168
+ if (element.type !== "application/json") {
169
+ return;
170
+ }
171
+
172
+ const d = JSON.parse(element.textContent);
173
+ if (data === null) {
174
+ if (isArray(d)) {
175
+ data = [];
176
+ } else {
177
+ data = {};
178
+ }
179
+ }
180
+
181
+ if (isArray(data) && !isArray(d)) {
182
+ throw new Error("Type mismatch");
183
+ }
184
+
185
+ if (!isArray(data) && isArray(d)) {
186
+ throw new Error("Type mismatch");
187
+ }
188
+
189
+ if (isArray(data)) {
190
+ data.push(...d);
191
+ return;
192
+ }
193
+
194
+ data = Object.assign({}, d);
195
+ });
196
+
197
+ if (data === null) {
198
+ data = [];
199
+ }
200
+
201
+ // set pagination
202
+ this.setOption("sys.pagination.objectsPerPage", 1);
203
+ this.setOption("sys.pagination.pages", data.length);
204
+ this.setOption("sys.pagination.currentPage", 1);
205
+
206
+ /** call setter */
207
+ this.data = data;
208
208
  }
209
209
 
210
210
  /**
@@ -212,8 +212,8 @@ function updateDataSource() {
212
212
  * @return {string}
213
213
  */
214
214
  function getTemplate() {
215
- // language=HTML
216
- return `
215
+ // language=HTML
216
+ return `
217
217
  <slot data-monster-role="datasource"></slot>`;
218
218
  }
219
219