- commit
- f67930393ed014b0180288ca16962a4dde8d8bad
- parent
- 92652cab5f3feedaffa8ab3a3f196d1ff8f57ed8
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2023-09-04 20:52
avoid using html2element for message
Diffstat
| M | content/js/message.js | 83 | +++++++++++++++++++++++++++++++++++++------------------------ |
| M | content/js/util.js | 37 | +++++++++++++++++-------------------- |
| M | content/main.html | 65 | ------------------------------------------------------------ |
3 files changed, 68 insertions, 117 deletions
diff --git a/content/js/message.js b/content/js/message.js
@@ -1,4 +1,4 @@1 -1 import Mustache from './mustache.mjs';-1 1 /* global browser */ 2 2 3 3 import createBody from './body.js'; 4 4 import * as actions from './actions.js'; @@ -41,46 +41,66 @@ var autoMarkAsRead = function(e, msg) { 41 41 }; 42 42 }; 43 4344 -1 var iconFilter = function() {45 -1 return function(text, render) {46 -1 var key = render(text);47 -1 return util.createIcon(key).outerHTML;48 -1 };-1 44 var createAuthor = function(author) { -1 45 var a = util.h('a', {'class': 'message__author', 'href': `mailto:${author.email}`}, [author.name]); -1 46 a.style.color = util.pseudoRandomColor(author.email); -1 47 return a; 49 48 }; 50 4951 -1 var dateFilter = function() {52 -1 return function(text, render) {53 -1 var date = new Date(render(text));54 -1 return util.createDate(date).outerHTML;55 -1 };56 -1 };57 -158 -1 var authorColorFilter = function() {59 -1 return function(text, render) {60 -1 return util.pseudoRandomColor(render(text));61 -1 };62 -1 };63 -164 -1 var stringFilter = function() {65 -1 return function(text, render) {66 -1 return browser.i18n.getMessage(render(text));67 -1 };-1 50 var template = function(ctx) { -1 51 var h = util.h; -1 52 return h('article', {'class': ctx.isExpanded ? 'message is-expanded' : 'message', 'id': `msg-${ctx.id}`, 'tabindex': -1}, [ -1 53 h('header', {'class': 'message__header'}, [ -1 54 h('button', {'class': ctx.isFlagged ? 'star is-active' : 'star', 'data-action': 'toggleFlagged'}, [util.createIcon('star')]), -1 55 createAuthor(ctx.author), -1 56 ' ', -1 57 h('span', {'class': 'message__recipients'}, [ -1 58 browser.i18n.getMessage('to'), -1 59 ' ', -1 60 ...ctx.recipients.map(r => h('a', {'href': `mailto:${r.email}`}, [r.name])), -1 61 ...ctx.cc.map(r => h('a', {'href': `mailto:${r.email}`, 'class': 'message__recipients__cc'}, [r.name])), -1 62 ...ctx.bcc.map(r => h('a', {'href': `mailto:${r.email}`, 'class': 'message__recipients__bcc'}, [r.name])), -1 63 ]), -1 64 h('span', {'class': 'message__summary'}, [ctx.summary]), -1 65 ctx.hasAttachments ? util.createIcon('attachment') : null, -1 66 util.createDate(ctx.date), -1 67 h('span', {'class': 'message__actions'}, [ -1 68 ctx.canReplyAll -1 69 ? h('button', {'class': 'button', 'title': browser.i18n.getMessage('replyAll'), 'data-action': 'replyAll'}, [util.createIcon('reply_all')]) -1 70 : ctx.canReplyToList -1 71 ? h('button', {'class': 'button', 'title': browser.i18n.getMessage('replyList'), 'data-action': 'replyToList'}, [util.createIcon('list')]) -1 72 : h('button', {'class': 'button', 'title': browser.i18n.getMessage('reply'), 'data-action': 'replyToSender'}, [util.createIcon('reply')]), -1 73 h('button', {'class': 'button dropdownToggle', 'title': browser.i18n.getMessage('more')}, [util.createIcon('menu')]), -1 74 h('div', {'class': 'dropdown'}, [ -1 75 h('button', {'class': 'dropdown-item', 'data-action': 'replyToSender'}, [util.createIcon('reply'), ' ', browser.i18n.getMessage('reply')]), -1 76 ctx.canReplyAll ? h('button', {'class': 'dropdown-item', 'data-action': 'replyAll'}, [util.createIcon('reply_all'), ' ', browser.i18n.getMessage('replyAll')]) : null, -1 77 ctx.canReplyToList ? h('button', {'class': 'dropdown-item', 'data-action': 'replyToList'}, [util.createIcon('list'), ' ', browser.i18n.getMessage('replyList')]) : null, -1 78 h('button', {'class': 'dropdown-item', 'data-action': 'forward'}, [util.createIcon('forward'), ' ', browser.i18n.getMessage('forward')]), -1 79 h('button', {'class': 'dropdown-item', 'data-action': 'editAsNew'}, [util.createIcon('create'), ' ', browser.i18n.getMessage('edit')]), -1 80 h('button', {'class': 'dropdown-item', 'data-action': 'viewClassic'}, [util.createIcon('open_in_new'), ' ', browser.i18n.getMessage('viewClassic')]), -1 81 h('button', {'class': 'dropdown-item', 'data-action': 'viewSource'}, [util.createIcon('code'), ' ', browser.i18n.getMessage('viewSource')]), -1 82 ]), -1 83 ]), -1 84 ]), -1 85 h('div', {'class': 'message__details'}, [ -1 86 ctx.isJunk ? util.createAlert(browser.i18n.getMessage('junk'), 'mode_heat', 'warning') : null, -1 87 h('footer', {'class': 'message__footer'}, [ -1 88 h('ul', {'class': 'attachments'}, (ctx.attachments || []).map(a => h('li', {}, [ -1 89 h('a', {'class': 'attachment', 'href': a.url}, [util.createIcon('attachment'), ' ', a.name]), -1 90 ]))), -1 91 ]), -1 92 ]), -1 93 ]); 68 94 }; 69 95 70 96 export default function(msg, expanded) {71 -1 var tpl = document.getElementById('message-template').innerHTML;72 -1 var html = Mustache.render(tpl, {73 -1 icon: iconFilter,74 -1 dateFilter: dateFilter,75 -1 authorColor: authorColorFilter,76 -1 str: stringFilter,77 -1-1 97 var e = template({ 78 98 id: msg.id, 79 99 isExpanded: expanded, 80 100 isFlagged: msg.flagged, 81 101 isJunk: msg.junk, 82 102 isEncrypted: msg.isEncrypted,83 -1 author: util.parseContacts([msg.author]),-1 103 author: util.parseContacts([msg.author])[0], 84 104 recipients: util.parseContacts(msg.recipients), 85 105 cc: util.parseContacts(msg.ccList), 86 106 bcc: util.parseContacts(msg.bccList), @@ -95,7 +115,6 @@ export default function(msg, expanded) { 95 115 + util.parseContacts(msg.bccList).length 96 116 ) > 1, 97 117 });98 -1 var e = util.html2element(html);99 118 100 119 autoMarkAsRead(e, msg); 101 120
diff --git a/content/js/util.js b/content/js/util.js
@@ -38,12 +38,17 @@ export var getBody = function(msgPart) {
38 38 }
39 39 };
40 40
41 -1 export var html2element = function(html) {
42 -1 // thunderbird 60 will remove some elements when directly assigning to
43 -1 // innerHTML
44 -1 var parser = new DOMParser();
45 -1 var doc = parser.parseFromString('<!DOCTYPE html>\n' + html, 'text/html');
46 -1 return doc.body.children[0];
-1 41 export var h = function(tag, attrs, children) {
-1 42 var el = document.createElement(tag);
-1 43 for (let attr in attrs) {
-1 44 el.setAttribute(attr, attrs[attr]);
-1 45 }
-1 46 for (let child of children) {
-1 47 if (child) {
-1 48 el.append(child);
-1 49 }
-1 50 }
-1 51 return el;
47 52 };
48 53
49 54 export var createIcon = function(key) {
@@ -62,23 +67,15 @@ export var createIcon = function(key) {
62 67
63 68 export var createDate = function(date) {
64 69 var now = new Date();
65 -1 var e = document.createElement('time');
66 -1 e.className = 'date';
67 -1 if (date.toDateString() === now.toDateString()) {
68 -1 e.textContent = date.toLocaleTimeString('sv');
69 -1 } else {
70 -1 e.textContent = date.toLocaleDateString('sv');
71 -1 }
72 -1 e.title = date.toLocaleString();
73 -1 return e;
-1 70 return h('time', {'class': 'date', 'title': date.toLocaleString()}, [
-1 71 date.toDateString() === now.toDateString()
-1 72 ? date.toLocaleTimeString('sv')
-1 73 : date.toLocaleDateString('sv')
-1 74 ]);
74 75 };
75 76
76 77 export var createAlert = function(text, icon, level) {
77 -1 var e = document.createElement('div');
78 -1 e.className = 'alert alert--' + level;
79 -1 e.textContent = text;
80 -1 e.prepend(createIcon(icon));
81 -1 return e;
-1 78 return h('div', {'class': `alert alert--${level}`}, [createIcon(icon), text]);
82 79 };
83 80
84 81 export var pseudoRandomColor = function(s) {
diff --git a/content/main.html b/content/main.html
@@ -6,71 +6,6 @@ 6 6 <link rel="stylesheet" href="style.css" /> 7 7 </head> 8 8 <body>9 -1 <script id="message-template" type="text/template">10 -1 <article class="message {{#isExpanded}}is-expanded{{/isExpanded}}" id="msg-{{ id }}" tabindex="-1">11 -1 <style>12 -1 {{#author}}13 -1 .message__author[href="mailto:{{ email }}"] { color: {{#authorColor}}{{ email }}{{/authorColor}} }14 -1 {{/author}}15 -1 </style>16 -1 <header class="message__header">17 -1 <button class="star {{#isFlagged}}is-active{{/isFlagged}}" data-action="toggleFlagged">{{#icon}}star{{/icon}}</button>18 -1 {{#author}}<a class="message__author" href="mailto:{{ email }}">{{ name }}</a>{{/author}}19 -1 <span class="message__recipients">20 -1 {{#str}}to{{/str}}21 -1 {{#recipients}}22 -1 <a href="mailto:{{ email }}">{{ name }}</a>23 -1 {{/recipients}}24 -1 {{#cc}}25 -1 <a class="message__recipients__cc" href="mailto:{{ email }}">{{ name }}</a>26 -1 {{/cc}}27 -1 {{#bcc}}28 -1 <a class="message__recipients__bcc" href="mailto:{{ email }}">{{ name }}</a>29 -1 {{/bcc}}30 -1 </span>31 -1 <span class="message__summary">{{ summary }}</span>32 -133 -1 {{#hasAttachments}}{{#icon}}attachment{{/icon}}{{/hasAttachments}}34 -1 {{#dateFilter}}{{ date }}{{/dateFilter}}35 -136 -1 <span class="message__actions">37 -1 {{#canReplyAll}}<button class="button" title="{{#str}}replyAll{{/str}}" data-action="replyAll">{{#icon}}reply_all{{/icon}}</button{{/canReplyAll}}38 -1 {{^canReplyAll}}39 -1 {{#canReplyToList}}<button class="button" title="{{#str}}replyList{{/str}}" data-action="replyToList">{{#icon}}list{{/icon}}</button{{/canReplyToList}}40 -1 {{^canReplyToList}}<button class="button" title="{{#str}}reply{{/str}}" data-action="replyToSender">{{#icon}}reply{{/icon}}</button{{/canReplyToList}}41 -1 {{/canReplyAll}}42 -143 -1 ><button class="button dropdownToggle" title="{{#str}}more{{/str}}">{{#icon}}menu{{/icon}}</button>44 -1 <div class="dropdown">45 -1 <button class="dropdown-item" data-action="replyToSender">{{#icon}}reply{{/icon}} {{#str}}reply{{/str}}</button>46 -1 {{#canReplyAll}}<button class="dropdown-item" data-action="replyAll">{{#icon}}reply_all{{/icon}} {{#str}}replyAll{{/str}}</button>{{/canReplyAll}}47 -1 {{#canReplyToList}}<button class="dropdown-item" data-action="replyToList">{{#icon}}list{{/icon}} {{#str}}replyList{{/str}}</button>{{/canReplyToList}}48 -1 <button class="dropdown-item" data-action="forward">{{#icon}}forward{{/icon}} {{#str}}forward{{/str}}</button>49 -1 <button class="dropdown-item" data-action="editAsNew">{{#icon}}create{{/icon}} {{#str}}edit{{/str}}</button>50 -1 <button class="dropdown-item" data-action="viewClassic">{{#icon}}open_in_new{{/icon}} {{#str}}viewClassic{{/str}}</button>51 -1 <button class="dropdown-item" data-action="viewSource">{{#icon}}code{{/icon}} {{#str}}viewSource{{/str}}</button>52 -1 </div>53 -1 </span>54 -1 </header>55 -156 -1 <div class="message__details">57 -1 {{#isJunk}}58 -1 <div class="alert alert--warning">{{#icon}}mode_heat{{/icon}} {{#str}}junk{{/str}}</div>59 -1 {{/isJunk}}60 -161 -1 <footer class="message__footer">62 -1 <ul class="attachments">63 -1 {{#attachments}}64 -1 <li>65 -1 <a class="attachment" href="{{ url }}">{{#icon}}attachment{{/icon}} {{ name }}</a>66 -1 </li>67 -1 {{/attachments}}68 -1 </ul>69 -1 </footer>70 -1 </div>71 -1 <article>72 -1 </script>73 -174 9 <header class="conversation__header"> 75 10 <h1 class="conversation__subject">Loading…</h1> 76 11 </header>