diff --git a/package.json b/package.json
index 275ef4c2..3cfbab52 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,8 @@
"matrix-react-sdk": "^0.0.1",
"q": "^1.4.1",
"react": "^0.13.3",
- "react-loader": "^1.4.0"
+ "react-loader": "^1.4.0",
+ "sanitize-html": "^1.11.1"
},
"devDependencies": {
"babel": "^5.8.23",
diff --git a/src/skins/vector/css/molecules/EventTile.css b/src/skins/vector/css/molecules/EventTile.css
index 3717ff54..eb59711e 100644
--- a/src/skins/vector/css/molecules/EventTile.css
+++ b/src/skins/vector/css/molecules/EventTile.css
@@ -66,6 +66,13 @@ limitations under the License.
margin-right: 100px;
}
+.mx_MessageTile_searchHighlight {
+ background-color: #76cfa6;
+ color: #fff;
+ border-radius: 5px;
+ padding: 4px;
+}
+
.mx_EventTile_sending {
color: #ddd;
}
@@ -78,6 +85,10 @@ limitations under the License.
color: #FF0064;
}
+.mx_EventTile_contextual {
+ opacity: 0.4;
+}
+
.mx_EventTile_msgOption {
float: right;
}
diff --git a/src/skins/vector/css/molecules/MTextTile.css b/src/skins/vector/css/molecules/MTextTile.css
index 5b117e41..96a9d1db 100644
--- a/src/skins/vector/css/molecules/MTextTile.css
+++ b/src/skins/vector/css/molecules/MTextTile.css
@@ -17,4 +17,3 @@ limitations under the License.
.mx_MTextTile {
white-space: pre-wrap;
}
-
diff --git a/src/skins/vector/views/molecules/EventTile.js b/src/skins/vector/views/molecules/EventTile.js
index bdd5c57b..3be02a5d 100644
--- a/src/skins/vector/views/molecules/EventTile.js
+++ b/src/skins/vector/views/molecules/EventTile.js
@@ -91,7 +91,8 @@ module.exports = React.createClass({
mx_EventTile_highlight: this.shouldHighlight(),
mx_EventTile_continuation: this.props.continuation,
mx_EventTile_last: this.props.last,
- menu: this.state.menu
+ mx_EventTile_contextual: this.props.contextual,
+ menu: this.state.menu,
});
var timestamp =
var editButton = (
@@ -126,7 +127,7 @@ module.exports = React.createClass({
{ timestamp }
{ editButton }
-
+
);
diff --git a/src/skins/vector/views/molecules/MNoticeTile.js b/src/skins/vector/views/molecules/MNoticeTile.js
index aa886127..e9ca85ea 100644
--- a/src/skins/vector/views/molecules/MNoticeTile.js
+++ b/src/skins/vector/views/molecules/MNoticeTile.js
@@ -17,18 +17,67 @@ limitations under the License.
'use strict';
var React = require('react');
+var sanitizeHtml = require('sanitize-html');
var MNoticeTileController = require('matrix-react-sdk/lib/controllers/molecules/MNoticeTile')
+var allowedAttributes = sanitizeHtml.defaults.allowedAttributes;
+allowedAttributes['font'] = ['color'];
+var sanitizeHtmlParams = {
+ allowedTags: sanitizeHtml.defaults.allowedTags.concat([ 'font' ]),
+ allowedAttributes: allowedAttributes,
+};
+
module.exports = React.createClass({
displayName: 'MNoticeTile',
mixins: [MNoticeTileController],
+ // FIXME: this entire class is copy-pasted from MTextTile :(
render: function() {
var content = this.props.mxEvent.getContent();
+ var body = content.body;
+
+ if (content.format === "org.matrix.custom.html") {
+ body = sanitizeHtml(content.formatted_body, sanitizeHtmlParams);
+ }
+
+ if (this.props.searchTerm) {
+ var lastOffset = 0;
+ var bodyList = [];
+ var k = 0;
+ var offset;
+ // XXX: this probably doesn't handle stemming very well.
+ while ((offset = body.indexOf(this.props.searchTerm, lastOffset)) >= 0) {
+ if (content.format === "org.matrix.custom.html") {
+ // FIXME: we need to apply the search highlighting to only the text elements of HTML, which means
+ // hooking into the sanitizer parser rather than treating it as a string. Otherwise
+ // the act of highlighting a or whatever will break the HTML badly.
+ bodyList.push();
+ bodyList.push();
+ }
+ else {
+ bodyList.push({ body.substring(lastOffset, offset) });
+ bodyList.push({ this.props.searchTerm });
+ }
+ lastOffset = offset + this.props.searchTerm.length;
+ }
+ if (content.format === "org.matrix.custom.html") {
+ bodyList.push();
+ }
+ else {
+ bodyList.push({ body.substring(lastOffset) });
+ }
+ body = bodyList;
+ }
+ else {
+ if (content.format === "org.matrix.custom.html") {
+ body = ;
+ }
+ }
+
return (
- {content.body}
+ { body }
);
},
diff --git a/src/skins/vector/views/molecules/MTextTile.js b/src/skins/vector/views/molecules/MTextTile.js
index 50555f94..6e04088e 100644
--- a/src/skins/vector/views/molecules/MTextTile.js
+++ b/src/skins/vector/views/molecules/MTextTile.js
@@ -17,18 +17,66 @@ limitations under the License.
'use strict';
var React = require('react');
+var sanitizeHtml = require('sanitize-html');
var MTextTileController = require('matrix-react-sdk/lib/controllers/molecules/MTextTile')
+var allowedAttributes = sanitizeHtml.defaults.allowedAttributes;
+allowedAttributes['font'] = ['color'];
+var sanitizeHtmlParams = {
+ allowedTags: sanitizeHtml.defaults.allowedTags.concat([ 'font' ]),
+ allowedAttributes: allowedAttributes,
+};
+
module.exports = React.createClass({
displayName: 'MTextTile',
mixins: [MTextTileController],
render: function() {
var content = this.props.mxEvent.getContent();
+ var body = content.body;
+
+ if (content.format === "org.matrix.custom.html") {
+ body = sanitizeHtml(content.formatted_body, sanitizeHtmlParams);
+ }
+
+ if (this.props.searchTerm) {
+ var lastOffset = 0;
+ var bodyList = [];
+ var k = 0;
+ var offset;
+ // XXX: this probably doesn't handle stemming very well.
+ while ((offset = body.indexOf(this.props.searchTerm, lastOffset)) >= 0) {
+ if (content.format === "org.matrix.custom.html") {
+ // FIXME: we need to apply the search highlighting to only the text elements of HTML, which means
+ // hooking into the sanitizer parser rather than treating it as a string. Otherwise
+ // the act of highlighting a or whatever will break the HTML badly.
+ bodyList.push();
+ bodyList.push();
+ }
+ else {
+ bodyList.push({ body.substring(lastOffset, offset) });
+ bodyList.push({ this.props.searchTerm });
+ }
+ lastOffset = offset + this.props.searchTerm.length;
+ }
+ if (content.format === "org.matrix.custom.html") {
+ bodyList.push();
+ }
+ else {
+ bodyList.push({ body.substring(lastOffset) });
+ }
+ body = bodyList;
+ }
+ else {
+ if (content.format === "org.matrix.custom.html") {
+ body = ;
+ }
+ }
+
return (
- {content.body}
+ { body }
);
},
diff --git a/src/skins/vector/views/molecules/MessageTile.js b/src/skins/vector/views/molecules/MessageTile.js
index 44f5b635..4386c13f 100644
--- a/src/skins/vector/views/molecules/MessageTile.js
+++ b/src/skins/vector/views/molecules/MessageTile.js
@@ -52,6 +52,6 @@ module.exports = React.createClass({
TileType = tileTypes[msgtype];
}
- return ;
+ return ;
},
});