1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
{{/*
The block editor's markup helpers and styles, shared by every page that
mounts one: the draft's own page, the index and a contact's conversation.
It is one defined template rather than markup repeated in each view for the
same reason the name partial is: three copies are three chances for one of
them to drift, and here the drift would be a page that loads the editor
script into a document that also frames a message.
"editorStyle" is the stylesheet. "replyButton" is the affordance that creates
a draft; it is a form so that it works with script disabled, in which case it
posts and lands on the draft's page. With script it is intercepted and the
editor appears in place. "editorScript" is the one <script> tag.
*/}}
{{define "replyButton"}}
<form class="de-reply" method="POST" action="/msg/{{.}}/reply" data-reply-form>
<button type="submit"
title="Compose a reply. Nothing is sent: this makes a draft you can edit.">↩ reply</button>
</form>
{{end}}
{{/*
"composeButton" starts a mail that answers nothing. Like the reply button it
is a form and not a link, because it creates something: a GET that made a
draft would let any prefetch litter the database, which is why /compose
refuses one. It carries no fields — the draft it makes is empty, and the
subject, the recipients and the text are all filled in on its own page, where
the list of who it goes to is visible.
*/}}
{{define "composeButton"}}
<form class="de-compose" method="POST" action="/compose">
<button type="submit"
title="Start a new mail. Nothing is sent: this makes an empty draft you can write and address.">✉ new mail</button>
</form>
{{end}}
{{define "editorScript"}}<script src="/static/draft-editor.js" defer></script>{{end}}
{{define "editorStyle"}}
.de-reply { display: inline-block; margin-top: 0.4rem; }
.de-reply button {
background: none; border: 1px solid var(--border); border-radius: 3px;
color: var(--link); font-size: 0.8rem; padding: 0.2rem 0.5rem;
cursor: pointer;
}
.de-reply button:hover { border-color: var(--link); }
.de-reply button:disabled { color: var(--text-meta); cursor: default; }
{{/* The compose button sits in a nav bar rather than under a message, so it
is styled as one of the links beside it. */}}
.de-compose { display: inline; }
.de-compose button {
background: none; border: none; padding: 0; cursor: pointer;
color: var(--link); font-size: inherit; font-family: inherit;
}
.de-compose button:hover { text-decoration: underline; }
.draft-editor {
margin-top: 0.6rem;
border: 1px solid var(--border); border-radius: 4px;
padding: 0.6rem 0.7rem;
background: var(--bg-card, transparent);
}
.de-head {
display: flex; align-items: baseline; gap: 0.6rem;
margin-bottom: 0.6rem; flex-wrap: wrap;
}
.de-subject {
flex: 1; min-width: 12rem; font: inherit; font-size: 0.95rem;
padding: 0.3rem 0.5rem;
border: 1px solid var(--border); border-radius: 3px;
background: var(--bg); color: var(--text);
}
.de-format, .de-status {
font-size: 0.75rem; color: var(--text-meta); white-space: nowrap;
}
.de-error { color: var(--danger, #c0392b); }
.de-notice {
font-size: 0.85rem; color: var(--text-meta);
border-left: 3px solid var(--border); padding-left: 0.6rem; margin: 0 0 0.6rem;
}
.de-muted { color: var(--text-meta); font-style: italic; font-size: 0.85rem; }
.de-block {
border: 1px solid var(--border); border-radius: 3px;
padding: 0.4rem 0.5rem; margin-bottom: 0.4rem;
background: var(--bg);
}
.de-block-quote { background: var(--bg-quote, var(--bg)); }
.de-dragging { opacity: 0.4; }
.de-drop-target { border-color: var(--link); border-style: dashed; }
.de-block-head {
display: flex; align-items: center; gap: 0.3rem;
font-size: 0.72rem; color: var(--text-meta); margin-bottom: 0.3rem;
}
.de-kind { text-transform: uppercase; letter-spacing: 0.05em; flex: 1; }
.de-handle { cursor: grab; user-select: none; padding: 0 0.2rem; }
.de-block-head button {
background: none; border: 1px solid transparent; border-radius: 3px;
color: var(--text-meta); cursor: pointer; font-size: 0.8rem;
padding: 0 0.3rem; line-height: 1.4;
}
.de-block-head button:hover { border-color: var(--border); color: var(--text); }
.de-block-head button.de-danger:hover { color: var(--danger, #c0392b); }
.de-attribution {
font-style: italic; color: var(--text-meta);
font-size: 0.78rem; margin-bottom: 0.3rem;
}
.de-block textarea {
width: 100%; font: inherit; font-size: 0.88rem; line-height: 1.45;
border: 1px solid var(--border); border-radius: 3px;
background: var(--bg); color: var(--text);
padding: 0.4rem; resize: vertical; box-sizing: border-box;
}
.de-block-code textarea {
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.82rem; white-space: pre;
}
.de-block input.de-meta {
width: 100%; font: inherit; font-size: 0.78rem; margin-bottom: 0.3rem;
border: 1px solid var(--border); border-radius: 3px;
background: var(--bg); color: var(--text); padding: 0.2rem 0.4rem;
box-sizing: border-box;
}
.de-add-bar { display: flex; gap: 0.3rem; flex-wrap: wrap; margin-top: 0.4rem; }
.de-add-bar button {
background: none; border: 1px solid var(--border); border-radius: 3px;
color: var(--text-meta); font-size: 0.78rem; padding: 0.2rem 0.5rem;
cursor: pointer;
}
.de-add-bar button:hover { color: var(--text); border-color: var(--text-meta); }
{{/* The real file input is hidden and clicked by the button beside it, so
that the control reads like the other three. The draft's own page has a
visible one, which is what works without script. */}}
.de-file-input { display: none; }
.de-file { display: flex; align-items: center; gap: 0.6rem; font-size: 0.85rem; }
.de-file img { max-width: 80px; max-height: 80px; border-radius: 3px; display: block; }
.de-file-meta { min-width: 0; word-break: break-word; }
.de-foot { margin-top: 0.5rem; font-size: 0.82rem; }
{{end}}
|