@etsoo/shared 1.1.83 → 1.1.85

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/README.md CHANGED
@@ -32,6 +32,15 @@ $ yarn add @etsoo/shared
32
32
  ## storage
33
33
  Storage interface and browser storage implementation
34
34
 
35
+ ## ContentDisposition
36
+ Content disposition of HTTP
37
+
38
+ |Name|Description|
39
+ |---:|---|
40
+ |static parse|Parse header value|
41
+ |Methods||
42
+ |format|Format to standard output|
43
+
35
44
  ## EColor
36
45
  Etsoo implmented Color
37
46
 
@@ -121,6 +130,8 @@ Data type definitions and type safe functions. ListItemType and ListItemType1 ar
121
130
  |MConstructor|Mixins constructor|
122
131
  |ObjType|Generic object type|
123
132
  |Optional|Make properties optional|
133
+ |PlacementEnum|Placement enum|
134
+ |Placement|Placement type|
124
135
  |RequireAtLeastOne|Require at least one property of the keys|
125
136
  |Simple|Basic or basic array type|
126
137
  |SimpleEnum|Simple type enum|
@@ -0,0 +1,24 @@
1
+ import { ContentDisposition } from '../src/types/ContentDisposition';
2
+
3
+ test('Tests for parse', () => {
4
+ const cd1 = ContentDisposition.parse(
5
+ "attachment; filename=__PDF.pdf; filename*=UTF-8''%E6%B5%8B%E8%AF%95PDF.pdf"
6
+ );
7
+
8
+ const cd2 = ContentDisposition.parse(
9
+ `attachment; filename="__PDF.pdf"; filename*="UTF-8''%E6%B5%8B%E8%AF%95PDF.pdf"`
10
+ );
11
+
12
+ expect(cd1?.type).toBe(cd2?.type);
13
+ expect(cd1?.filename).toBe(cd2?.filename);
14
+ expect(cd1?.filename).toBe('测试PDF.pdf');
15
+ });
16
+
17
+ test('Tests for format', () => {
18
+ const cd1 = new ContentDisposition('form-data', 'a-b.jpg', 'file');
19
+ expect(cd1.format()).toBe(`form-data; name="file"; filename="a-b.jpg"`);
20
+ const cd2 = new ContentDisposition('attachment', '测试PDF.pdf');
21
+ expect(cd2.format()).toBe(
22
+ `attachment; filename="__PDF.pdf"; filename*="UTF-8''%E6%B5%8B%E8%AF%95PDF.pdf"`
23
+ );
24
+ });
@@ -114,6 +114,25 @@ export declare namespace DataTypes {
114
114
  * Vertical align
115
115
  */
116
116
  type VAlign = Lowercase<keyof typeof VAlignEnum>;
117
+ /**
118
+ * Placement enum
119
+ */
120
+ enum PlacementEnum {
121
+ TopLeft = 0,
122
+ TopCenter = 1,
123
+ TopRight = 2,
124
+ MiddleLeft = 3,
125
+ Center = 4,
126
+ MiddleRight = 5,
127
+ BottomLeft = 6,
128
+ BottomCenter = 7,
129
+ BottomRight = 8,
130
+ Unknown = 9
131
+ }
132
+ /**
133
+ * Placement type
134
+ */
135
+ type Placement = keyof typeof PlacementEnum;
117
136
  /**
118
137
  * Number and string combination id type
119
138
  */
@@ -76,6 +76,22 @@ var DataTypes;
76
76
  VAlignEnum[VAlignEnum["Center"] = 2] = "Center";
77
77
  VAlignEnum[VAlignEnum["Bottom"] = 3] = "Bottom";
78
78
  })(VAlignEnum = DataTypes.VAlignEnum || (DataTypes.VAlignEnum = {}));
79
+ /**
80
+ * Placement enum
81
+ */
82
+ let PlacementEnum;
83
+ (function (PlacementEnum) {
84
+ PlacementEnum[PlacementEnum["TopLeft"] = 0] = "TopLeft";
85
+ PlacementEnum[PlacementEnum["TopCenter"] = 1] = "TopCenter";
86
+ PlacementEnum[PlacementEnum["TopRight"] = 2] = "TopRight";
87
+ PlacementEnum[PlacementEnum["MiddleLeft"] = 3] = "MiddleLeft";
88
+ PlacementEnum[PlacementEnum["Center"] = 4] = "Center";
89
+ PlacementEnum[PlacementEnum["MiddleRight"] = 5] = "MiddleRight";
90
+ PlacementEnum[PlacementEnum["BottomLeft"] = 6] = "BottomLeft";
91
+ PlacementEnum[PlacementEnum["BottomCenter"] = 7] = "BottomCenter";
92
+ PlacementEnum[PlacementEnum["BottomRight"] = 8] = "BottomRight";
93
+ PlacementEnum[PlacementEnum["Unknown"] = 9] = "Unknown"; // Reserved for modal, only one instance held at the same time
94
+ })(PlacementEnum = DataTypes.PlacementEnum || (DataTypes.PlacementEnum = {}));
79
95
  /**
80
96
  * Convert value to target type
81
97
  * @param input Input value
@@ -79,16 +79,12 @@ export declare namespace DomUtils {
79
79
  const getCulture: <T extends DataTypes.StringRecord>(items: Readonly<{
80
80
  name: string;
81
81
  label: string;
82
- resources: T; /**
83
- * Current detected culture
84
- */
82
+ resources: T;
85
83
  compatibleNames?: string[] | undefined;
86
84
  }>[], culture: string) => [Readonly<{
87
85
  name: string;
88
86
  label: string;
89
- resources: T; /**
90
- * Current detected culture
91
- */
87
+ resources: T;
92
88
  compatibleNames?: string[] | undefined;
93
89
  }> | undefined, CultureMatch];
94
90
  /**
@@ -1,3 +1,4 @@
1
+ export * from './types/ContentDisposition';
1
2
  export * from './types/DelayedExecutorType';
2
3
  export * from './types/EColor';
3
4
  export * from './types/EHistory';
package/lib/cjs/index.js CHANGED
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types/ContentDisposition"), exports);
17
18
  __exportStar(require("./types/DelayedExecutorType"), exports);
18
19
  __exportStar(require("./types/EColor"), exports);
19
20
  __exportStar(require("./types/EHistory"), exports);
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Content disposition of HTTP
3
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
4
+ */
5
+ export declare class ContentDisposition {
6
+ readonly type: string;
7
+ readonly filename: string;
8
+ readonly name?: string | undefined;
9
+ constructor(type: 'inline' | 'attachment', filename: string);
10
+ constructor(type: 'form-data', filename: string, name: string);
11
+ /**
12
+ * Format to standard output
13
+ * @returns Result
14
+ */
15
+ format(): string;
16
+ /**
17
+ * Parse header value
18
+ * @param header Content-Disposition header value
19
+ * @returns Object
20
+ */
21
+ static parse(header: string | undefined | null): ContentDisposition | undefined;
22
+ }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContentDisposition = void 0;
4
+ const Utils_1 = require("../Utils");
5
+ /**
6
+ * Content disposition of HTTP
7
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
8
+ */
9
+ class ContentDisposition {
10
+ constructor(type, filename, name) {
11
+ this.type = type;
12
+ this.filename = filename;
13
+ this.name = name;
14
+ }
15
+ /**
16
+ * Format to standard output
17
+ * @returns Result
18
+ */
19
+ format() {
20
+ const items = [this.type];
21
+ if (this.name)
22
+ items.push(`name="${this.name}"`);
23
+ const filename1 = this.filename.replace(/[^a-zA-Z0-9\.-]/g, '_');
24
+ items.push(`filename="${filename1}"`);
25
+ if (filename1 != this.filename)
26
+ items.push(`filename*="UTF-8''${encodeURIComponent(this.filename)}"`);
27
+ return items.join('; ');
28
+ }
29
+ /**
30
+ * Parse header value
31
+ * @param header Content-Disposition header value
32
+ * @returns Object
33
+ */
34
+ static parse(header) {
35
+ if (!header)
36
+ return undefined;
37
+ const parts = header.trim().split(/\s*;\s*/g);
38
+ const len = parts.length;
39
+ if (len < 2)
40
+ return undefined;
41
+ const type = parts[0];
42
+ let name;
43
+ let filename = '';
44
+ for (let i = 1; i < len; i++) {
45
+ const part = parts[i];
46
+ let [field, value] = part.split(/\s*=\s*/g);
47
+ // case-insensitive
48
+ field = field.toLowerCase();
49
+ // Remove quotes
50
+ value = Utils_1.Utils.trim(value, '"');
51
+ if (field === 'name') {
52
+ name = value;
53
+ }
54
+ else if (field === 'filename') {
55
+ if (filename === '')
56
+ filename = value;
57
+ }
58
+ else if (field === 'filename*') {
59
+ const pos = value.indexOf("''");
60
+ filename =
61
+ pos == -1
62
+ ? value
63
+ : decodeURIComponent(value.substring(pos + 2));
64
+ }
65
+ }
66
+ if (type === 'form-data') {
67
+ return new ContentDisposition(type, filename, name !== null && name !== void 0 ? name : 'file');
68
+ }
69
+ if (type === 'inline' || type === 'attachment') {
70
+ return new ContentDisposition(type, filename);
71
+ }
72
+ return undefined;
73
+ }
74
+ }
75
+ exports.ContentDisposition = ContentDisposition;
@@ -114,6 +114,25 @@ export declare namespace DataTypes {
114
114
  * Vertical align
115
115
  */
116
116
  type VAlign = Lowercase<keyof typeof VAlignEnum>;
117
+ /**
118
+ * Placement enum
119
+ */
120
+ enum PlacementEnum {
121
+ TopLeft = 0,
122
+ TopCenter = 1,
123
+ TopRight = 2,
124
+ MiddleLeft = 3,
125
+ Center = 4,
126
+ MiddleRight = 5,
127
+ BottomLeft = 6,
128
+ BottomCenter = 7,
129
+ BottomRight = 8,
130
+ Unknown = 9
131
+ }
132
+ /**
133
+ * Placement type
134
+ */
135
+ type Placement = keyof typeof PlacementEnum;
117
136
  /**
118
137
  * Number and string combination id type
119
138
  */
@@ -73,6 +73,22 @@ export var DataTypes;
73
73
  VAlignEnum[VAlignEnum["Center"] = 2] = "Center";
74
74
  VAlignEnum[VAlignEnum["Bottom"] = 3] = "Bottom";
75
75
  })(VAlignEnum = DataTypes.VAlignEnum || (DataTypes.VAlignEnum = {}));
76
+ /**
77
+ * Placement enum
78
+ */
79
+ let PlacementEnum;
80
+ (function (PlacementEnum) {
81
+ PlacementEnum[PlacementEnum["TopLeft"] = 0] = "TopLeft";
82
+ PlacementEnum[PlacementEnum["TopCenter"] = 1] = "TopCenter";
83
+ PlacementEnum[PlacementEnum["TopRight"] = 2] = "TopRight";
84
+ PlacementEnum[PlacementEnum["MiddleLeft"] = 3] = "MiddleLeft";
85
+ PlacementEnum[PlacementEnum["Center"] = 4] = "Center";
86
+ PlacementEnum[PlacementEnum["MiddleRight"] = 5] = "MiddleRight";
87
+ PlacementEnum[PlacementEnum["BottomLeft"] = 6] = "BottomLeft";
88
+ PlacementEnum[PlacementEnum["BottomCenter"] = 7] = "BottomCenter";
89
+ PlacementEnum[PlacementEnum["BottomRight"] = 8] = "BottomRight";
90
+ PlacementEnum[PlacementEnum["Unknown"] = 9] = "Unknown"; // Reserved for modal, only one instance held at the same time
91
+ })(PlacementEnum = DataTypes.PlacementEnum || (DataTypes.PlacementEnum = {}));
76
92
  /**
77
93
  * Convert value to target type
78
94
  * @param input Input value
@@ -79,16 +79,12 @@ export declare namespace DomUtils {
79
79
  const getCulture: <T extends DataTypes.StringRecord>(items: Readonly<{
80
80
  name: string;
81
81
  label: string;
82
- resources: T; /**
83
- * Current detected culture
84
- */
82
+ resources: T;
85
83
  compatibleNames?: string[] | undefined;
86
84
  }>[], culture: string) => [Readonly<{
87
85
  name: string;
88
86
  label: string;
89
- resources: T; /**
90
- * Current detected culture
91
- */
87
+ resources: T;
92
88
  compatibleNames?: string[] | undefined;
93
89
  }> | undefined, CultureMatch];
94
90
  /**
@@ -1,3 +1,4 @@
1
+ export * from './types/ContentDisposition';
1
2
  export * from './types/DelayedExecutorType';
2
3
  export * from './types/EColor';
3
4
  export * from './types/EHistory';
package/lib/mjs/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './types/ContentDisposition';
1
2
  export * from './types/DelayedExecutorType';
2
3
  export * from './types/EColor';
3
4
  export * from './types/EHistory';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Content disposition of HTTP
3
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
4
+ */
5
+ export declare class ContentDisposition {
6
+ readonly type: string;
7
+ readonly filename: string;
8
+ readonly name?: string | undefined;
9
+ constructor(type: 'inline' | 'attachment', filename: string);
10
+ constructor(type: 'form-data', filename: string, name: string);
11
+ /**
12
+ * Format to standard output
13
+ * @returns Result
14
+ */
15
+ format(): string;
16
+ /**
17
+ * Parse header value
18
+ * @param header Content-Disposition header value
19
+ * @returns Object
20
+ */
21
+ static parse(header: string | undefined | null): ContentDisposition | undefined;
22
+ }
@@ -0,0 +1,71 @@
1
+ import { Utils } from '../Utils';
2
+ /**
3
+ * Content disposition of HTTP
4
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
5
+ */
6
+ export class ContentDisposition {
7
+ constructor(type, filename, name) {
8
+ this.type = type;
9
+ this.filename = filename;
10
+ this.name = name;
11
+ }
12
+ /**
13
+ * Format to standard output
14
+ * @returns Result
15
+ */
16
+ format() {
17
+ const items = [this.type];
18
+ if (this.name)
19
+ items.push(`name="${this.name}"`);
20
+ const filename1 = this.filename.replace(/[^a-zA-Z0-9\.-]/g, '_');
21
+ items.push(`filename="${filename1}"`);
22
+ if (filename1 != this.filename)
23
+ items.push(`filename*="UTF-8''${encodeURIComponent(this.filename)}"`);
24
+ return items.join('; ');
25
+ }
26
+ /**
27
+ * Parse header value
28
+ * @param header Content-Disposition header value
29
+ * @returns Object
30
+ */
31
+ static parse(header) {
32
+ if (!header)
33
+ return undefined;
34
+ const parts = header.trim().split(/\s*;\s*/g);
35
+ const len = parts.length;
36
+ if (len < 2)
37
+ return undefined;
38
+ const type = parts[0];
39
+ let name;
40
+ let filename = '';
41
+ for (let i = 1; i < len; i++) {
42
+ const part = parts[i];
43
+ let [field, value] = part.split(/\s*=\s*/g);
44
+ // case-insensitive
45
+ field = field.toLowerCase();
46
+ // Remove quotes
47
+ value = Utils.trim(value, '"');
48
+ if (field === 'name') {
49
+ name = value;
50
+ }
51
+ else if (field === 'filename') {
52
+ if (filename === '')
53
+ filename = value;
54
+ }
55
+ else if (field === 'filename*') {
56
+ const pos = value.indexOf("''");
57
+ filename =
58
+ pos == -1
59
+ ? value
60
+ : decodeURIComponent(value.substring(pos + 2));
61
+ }
62
+ }
63
+ if (type === 'form-data') {
64
+ return new ContentDisposition(type, filename, name !== null && name !== void 0 ? name : 'file');
65
+ }
66
+ if (type === 'inline' || type === 'attachment') {
67
+ return new ContentDisposition(type, filename);
68
+ }
69
+ return undefined;
70
+ }
71
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/shared",
3
- "version": "1.1.83",
3
+ "version": "1.1.85",
4
4
  "description": "TypeScript shared utilities and functions",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -54,13 +54,8 @@
54
54
  },
55
55
  "homepage": "https://github.com/ETSOO/Shared#readme",
56
56
  "devDependencies": {
57
- "@types/jest": "^29.2.4",
57
+ "@types/jest": "^29.2.5",
58
58
  "@types/lodash.isequal": "^4.5.6",
59
- "@typescript-eslint/eslint-plugin": "^5.46.1",
60
- "@typescript-eslint/parser": "^5.46.1",
61
- "eslint": "^8.30.0",
62
- "eslint-config-airbnb-base": "^15.0.0",
63
- "eslint-plugin-import": "^2.26.0",
64
59
  "jest": "^29.3.1",
65
60
  "jest-environment-jsdom": "^29.3.1",
66
61
  "ts-jest": "^29.0.3",
package/src/DataTypes.ts CHANGED
@@ -148,6 +148,30 @@ export namespace DataTypes {
148
148
  */
149
149
  export type VAlign = Lowercase<keyof typeof VAlignEnum>;
150
150
 
151
+ /**
152
+ * Placement enum
153
+ */
154
+ export enum PlacementEnum {
155
+ TopLeft,
156
+ TopCenter,
157
+ TopRight,
158
+
159
+ MiddleLeft,
160
+ Center,
161
+ MiddleRight,
162
+
163
+ BottomLeft,
164
+ BottomCenter,
165
+ BottomRight,
166
+
167
+ Unknown // Reserved for modal, only one instance held at the same time
168
+ }
169
+
170
+ /**
171
+ * Placement type
172
+ */
173
+ export type Placement = keyof typeof PlacementEnum;
174
+
151
175
  /**
152
176
  * Number and string combination id type
153
177
  */
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './types/ContentDisposition';
1
2
  export * from './types/DelayedExecutorType';
2
3
  export * from './types/EColor';
3
4
  export * from './types/EHistory';
@@ -0,0 +1,81 @@
1
+ import { Utils } from '../Utils';
2
+
3
+ /**
4
+ * Content disposition of HTTP
5
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
6
+ */
7
+ export class ContentDisposition {
8
+ constructor(type: 'inline' | 'attachment', filename: string);
9
+ constructor(type: 'form-data', filename: string, name: string);
10
+ constructor(
11
+ public readonly type: string,
12
+ public readonly filename: string,
13
+ public readonly name?: string
14
+ ) {}
15
+
16
+ /**
17
+ * Format to standard output
18
+ * @returns Result
19
+ */
20
+ format() {
21
+ const items = [this.type];
22
+ if (this.name) items.push(`name="${this.name}"`);
23
+ const filename1 = this.filename.replace(/[^a-zA-Z0-9\.-]/g, '_');
24
+ items.push(`filename="${filename1}"`);
25
+ if (filename1 != this.filename)
26
+ items.push(
27
+ `filename*="UTF-8''${encodeURIComponent(this.filename)}"`
28
+ );
29
+ return items.join('; ');
30
+ }
31
+
32
+ /**
33
+ * Parse header value
34
+ * @param header Content-Disposition header value
35
+ * @returns Object
36
+ */
37
+ static parse(header: string | undefined | null) {
38
+ if (!header) return undefined;
39
+
40
+ const parts = header.trim().split(/\s*;\s*/g);
41
+ const len = parts.length;
42
+ if (len < 2) return undefined;
43
+
44
+ const type = parts[0];
45
+ let name: string | undefined;
46
+ let filename: string = '';
47
+
48
+ for (let i = 1; i < len; i++) {
49
+ const part = parts[i];
50
+ let [field, value] = part.split(/\s*=\s*/g);
51
+
52
+ // case-insensitive
53
+ field = field.toLowerCase();
54
+
55
+ // Remove quotes
56
+ value = Utils.trim(value, '"');
57
+
58
+ if (field === 'name') {
59
+ name = value;
60
+ } else if (field === 'filename') {
61
+ if (filename === '') filename = value;
62
+ } else if (field === 'filename*') {
63
+ const pos = value.indexOf("''");
64
+ filename =
65
+ pos == -1
66
+ ? value
67
+ : decodeURIComponent(value.substring(pos + 2));
68
+ }
69
+ }
70
+
71
+ if (type === 'form-data') {
72
+ return new ContentDisposition(type, filename, name ?? 'file');
73
+ }
74
+
75
+ if (type === 'inline' || type === 'attachment') {
76
+ return new ContentDisposition(type, filename);
77
+ }
78
+
79
+ return undefined;
80
+ }
81
+ }