@remit/ui 0.0.109 → 0.0.110
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/package.json +1 -1
- package/src/components/compose-action-bar.render.test.ts +7 -5
- package/src/components/compose-action-bar.stories.tsx +36 -19
- package/src/components/compose-action-bar.tsx +31 -23
- package/src/components/compose-body-skeleton.tsx +10 -0
- package/src/components/compose-body.stories.tsx +66 -1
- package/src/components/compose-body.tsx +11 -6
- package/src/components/compose-header.stories.tsx +27 -1
- package/src/components/compose-header.tsx +18 -6
- package/src/components/compose-language-chip.stories.tsx +35 -1
- package/src/components/compose-language-chip.tsx +20 -2
- package/src/components/compose-smtp-missing-banner.tsx +15 -3
- package/src/components/plain-text-editor.mount.test.ts +4 -4
- package/src/components/plain-text-editor.stories.tsx +1 -0
- package/src/components/plain-text-editor.tsx +20 -14
- package/src/components/rich-text-editor.stories.tsx +54 -0
- package/src/components/rich-text-editor.tsx +20 -8
- package/src/components/rich-text-formatting.test.ts +3 -2
- package/src/components/rich-text-image-node.test.ts +157 -0
- package/src/components/rich-text-image-node.ts +124 -0
- package/src/components/rich-text-nodes.ts +5 -1
- package/src/components/rich-text-paste.test.ts +48 -0
- package/src/components/rich-text-value.ts +6 -0
- package/src/index.ts +3 -0
- package/src/lib/adopted-html.test.ts +23 -0
- package/src/lib/adopted-html.ts +16 -1
- package/src/rich-text.ts +1 -0
package/src/index.ts
CHANGED
|
@@ -129,12 +129,14 @@ export {
|
|
|
129
129
|
ComposeActionBar,
|
|
130
130
|
type ComposeActionBarProps,
|
|
131
131
|
type ComposeSaveStatus,
|
|
132
|
+
type ComposeSendState,
|
|
132
133
|
} from "./components/compose-action-bar.js";
|
|
133
134
|
export {
|
|
134
135
|
type AddressEntry,
|
|
135
136
|
ComposeAddressField,
|
|
136
137
|
type ComposeAddressFieldProps,
|
|
137
138
|
} from "./components/compose-address-field.js";
|
|
139
|
+
export { ComposeBodySkeleton } from "./components/compose-body-skeleton.js";
|
|
138
140
|
export {
|
|
139
141
|
ComposeFormShell,
|
|
140
142
|
type ComposeFormShellProps,
|
|
@@ -153,6 +155,7 @@ export {
|
|
|
153
155
|
export {
|
|
154
156
|
ComposeSmtpMissingBanner,
|
|
155
157
|
type ComposeSmtpMissingBannerProps,
|
|
158
|
+
SMTP_MISSING_MESSAGE,
|
|
156
159
|
} from "./components/compose-smtp-missing-banner.js";
|
|
157
160
|
export {
|
|
158
161
|
ComposeSubjectField,
|
|
@@ -124,6 +124,29 @@ describe("sanitizeAdoptedHtml", () => {
|
|
|
124
124
|
assert.equal(result.includes("tracker.gif"), false);
|
|
125
125
|
assert.equal(result.includes("cid:part1"), false);
|
|
126
126
|
});
|
|
127
|
+
|
|
128
|
+
it("caps an image at the width the recipient has for it", () => {
|
|
129
|
+
const result = sanitizeAdoptedHtml(
|
|
130
|
+
'<img src="https://example.com/screenshot.png" width="1600">',
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
assert.match(result, /style="max-width:100%;height:auto"/);
|
|
134
|
+
assert.equal(result.includes("1600"), false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("writes that cap itself rather than trusting the source", () => {
|
|
138
|
+
const result = sanitizeAdoptedHtml(
|
|
139
|
+
[
|
|
140
|
+
'<img src="https://example.com/a.png" style="width:1600px;border:8px solid red">',
|
|
141
|
+
'<p style="color:red">Text</p>',
|
|
142
|
+
].join(""),
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
assert.equal(result.includes("1600px"), false);
|
|
146
|
+
assert.equal(result.includes("border"), false);
|
|
147
|
+
assert.equal(result.includes("color:red"), false);
|
|
148
|
+
assert.match(result, /<img src="https:\/\/example.com\/a.png"/);
|
|
149
|
+
});
|
|
127
150
|
});
|
|
128
151
|
|
|
129
152
|
describe("sanitizeQuotedHtml", () => {
|
package/src/lib/adopted-html.ts
CHANGED
|
@@ -63,6 +63,17 @@ const ADOPTED_ATTR = [
|
|
|
63
63
|
const LINK_SCHEMES = /^(?:https?:|mailto:)/i;
|
|
64
64
|
const IMAGE_SCHEMES = /^(?:https:|data:image\/)/i;
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* A pasted screenshot is as wide as the screen it came off, and the class the
|
|
68
|
+
* editor draws it with is this app's own presentation — it does not leave with
|
|
69
|
+
* the message. So the one constraint that has to survive is written here, on
|
|
70
|
+
* the way out, rather than admitted from whoever wrote the source: `style`
|
|
71
|
+
* stays out of ADOPTED_ATTR, and an image carries this declaration and no
|
|
72
|
+
* other. Whether a `data:` image reaches a given client at all is a separate
|
|
73
|
+
* question (#679).
|
|
74
|
+
*/
|
|
75
|
+
const IMAGE_SIZE = "max-width:100%;height:auto";
|
|
76
|
+
|
|
66
77
|
/**
|
|
67
78
|
* `"quoted"` is mail rendered back at its sender, and it renders in the app's
|
|
68
79
|
* own document rather than in the reading pane's sandboxed frame. A link in it
|
|
@@ -96,7 +107,11 @@ const createPurifier = (profile: Profile): ReturnType<typeof DOMPurify> => {
|
|
|
96
107
|
node.remove();
|
|
97
108
|
return;
|
|
98
109
|
}
|
|
99
|
-
if (!IMAGE_SCHEMES.test(node.getAttribute("src") ?? ""))
|
|
110
|
+
if (!IMAGE_SCHEMES.test(node.getAttribute("src") ?? "")) {
|
|
111
|
+
node.remove();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
node.setAttribute("style", IMAGE_SIZE);
|
|
100
115
|
});
|
|
101
116
|
return instance;
|
|
102
117
|
};
|