-
Notifications
You must be signed in to change notification settings - Fork 0
/
uggly.proto
349 lines (310 loc) · 13.7 KB
/
uggly.proto
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
syntax = "proto3";
option go_package = "github.com/rendicott/uggly";
package uggly;
/* DivBox is a core element of the protocol. No content can exist
outside of a DivBox. It requires that some basic properties are included
such as fill and border geometry but the rawContents property is open
to fill with whatever content is desired.
*/
message DivBox {
string name = 9; // the name of the divBox. Used when attaching TextBlobs and forms
bool border = 10; // whether the div should add a border
// the width of the border, will stay inside the stated overall dimensions
// and work its way inward
int32 borderW = 11;
// The character to use as a border character (e.g., "#") but represented as rune
// For example, in Python this would be 'ord("#")' and Go it would be
// []rune("#")[0]
int32 borderChar = 12;
// if the DivBox should be filled with a char as a texture. Follows same
// rune rules as borderChar.
int32 fillChar = 14;
int32 startX = 15; // position on the X axis where the box should start
int32 startY = 16; // position on the Y axis where the box should start
int32 width = 17; // overall width of the box
int32 Height = 18;// overall height of the box
Style borderSt = 20; // style to use when rendering border char
Style fillSt = 21; // style to use when rendering fill char
}
/* TextBlob is a special kind of element that natively understands
text blocks intended for human readability. Obviously it has a content
property but also understands things like text style and text wrap when
the text is larger than the width of the container it was assigned to.
A TextBlob can be assigned to multiple Divs in case you wanted to re-use
text in multiple places for some reason.
*/
message TextBlob {
// The actual content. Could be almost any length but be aware
// of the size of the containing div.
string content = 10;
bool wrap = 11; // whether or not the text should wrap if it exceeds the width of it's divbox
Style style = 12;
repeated string divNames = 15; // the divs this text should be attached to. Generally it's just one.
}
/* Style is a base property used in divBox fill, border fill, and textboxes
with fg being foreground color, bg being background color, and attr
being text attributes like strikethrough and underline.
It's essentially a passthrough of the capabilities of tcell's style
https://github.com/gdamore/tcell/blob/master/style.go
*/
message Style {
string fg = 10; // a string representation of the color for the foreground (i.e., text)
string bg = 11;// a string representation of the color for the background
// attr would be things like underline or bold if the client terminal supports it.
// Experimentation with this has proven that '4' is the only dependable value
string attr = 12;
}
// Link contains information about keyboard shortcuts
// and destinations for actions. The client will determine
// from context whether a Link is to a server page or is
// to be used to pass polling context to a Form that it
// already receieved in a PageResponse.
message Link {
// a repeat of the keystroke used in the parent KeyStroke
// TODO: not sure what happens if they don't match
string keyStroke = 10;
// the name of the page to be requested in the new PageRequest
string pageName = 11;
string server = 12; // the server to be used in the new PageRequest
string port = 13; // the port to be used in the new PageRequest
bool secure = 16; // whether or not the new PageRequest should be secure (TLS)
bool stream = 17; // whether or not the new PageRequest is a stream
}
// If a KeyStroke is of type DivScroll
// then this contains information about which
// DivBox to scroll and whether or not the direction
// is down = true or down = false (e.g., 'up')
//
// WARNING: Not currently implemented in 'uggly-client'
message DivScroll {
string divName = 10;
bool down = 11;
}
// If a KeyStroke is of type FormActivation
// then this contains the name of the form which
// should be activated for that keystroke
message FormActivation {
string formName = 10;
}
// KeyStroke indicates an action that will be executed when the keyStroke
// is prssed by the client. This could be one of Link (e.g., new PageRequest),
// DivScroll (indicates the client should attempt to re-render textblobs that
// exceed their containing DivBox's capacity), or FormActivation which would
// look for a form with the given name on the client's current page.
message KeyStroke {
// a string representation of a key on a keyboard. For rune keys
// (e.g., "j") simply use the single character. For more complex
// keys refer to the string representation from the tcell package:
// https://github.com/gdamore/tcell/blob/master/key.go#L83
//
// The client may have certain keys reserved that will never be
// honored. In the current "uggly-client" this includes:
// F1, F2, F3, F4, F5, F6, F7, and F10
string keyStroke = 10;
oneof Action {
Link link = 20;
DivScroll divScroll = 21;
FormActivation formActivation = 22;
}
}
// TextBox contains the properties sent by the server
// for the client to render.
message TextBox {
// the name of this textBox. Will be used as the key in the key:value
// during submission
string name = 10;
// the order in which this field will activate when user is tabbing
// through form fields
int32 tabOrder = 11;
string defaultValue = 12; // the default value that will be placed in the box
// a description of the text box (e.g., "passwords should include special chars")
// which can optionally be drawn to the left of the textbox
string description = 13;
int32 positionX = 14; // relative within DivBox
int32 positionY = 15; // relative within DivBox
int32 height = 16; // currently textBoxes only utilize a single line
int32 width = 17; // text that goes beyond the width will horozontially scroll to fit
// style for the cursor within the box. ForeGround color is meaningless
Style styleCursor = 18;
// style for the box fill or background. Foreground and Background should probably
// match styleText so as not to clash
Style styleFill = 19;
// style of the text that is being typed into box.
Style styleText = 20;
// style for the description that is rendered to the left of the box
Style styleDescription = 21;
// whether or not to render the description. Design consideration:
// This will be rendered as far to the left of the textBox's positionX
// attribute as to fit the description.
bool showDescription = 22;
// whether or not this field is a password, e.g, it's contents will be hidden
// while typing
bool password = 23;
}
// The Form is sent by the server to the client
// as part of the PageResponse. It contains
// the Form name, the DivBox it should be placed
// within (TextBox PositionX and Y coordinates
// are relative to the containing DivBox) and a
// list of the TextBox's included in this form.
// It also supports a parameter for a Link that can
// be used as a return address when this Form is
// submitted in a PageRequest
message Form {
// The name of the form. This will be used in formActivation keystrokes and
// for atributing formData in PageRequests
string name = 10;
// the DivName that the form should be rendered within. All of the elements of
// the form will be rendered relative to this divBox
string divName = 11;
// The textboxes to be included in this form
repeated TextBox textBoxes = 12;
// The link that this form will call when the form's submit action
// (e.g., 'enter') is triggered
Link submitLink = 13;
}
// FormData contains the form name and any
// TextBoxData that was in the form when
// the FormData was sent in the PageRequest
message FormData {
string name = 10;
repeated TextBoxData textBoxData = 11;
}
// TextBoxData contains the text box's field
// name and whatever contents were in it
// when the PageRequest was sent with FormData
message TextBoxData {
string name = 10;
string contents = 11;
}
// Elements contains all non-DivBox related
// content that could be included in a PageResponse.
// Right now this contains TextBlobs and Forms
// but will be used for future elements if needed.
// For example, if determined that clients should
// handle all Table rendering in the future or something.
// Right now tables would have to be stick built by
// the server using DivBoxes and TextBlobs
message Elements {
repeated TextBlob textBlobs = 10;
repeated Form forms = 11;
}
// A PageListing is basically a key/value
// pair of page name and an optional
// description. The client can choose to render
// this however it wants and the client injects
// it's own "links" to this content. This is a
// lazy way of exposing all the server's content
// without having to build nav menus and manage
// links
message PageListing {
string name = 10;
string description = 11;
}
/* DivBoxes is an array of DivBox */
message DivBoxes {
repeated DivBox boxes = 10;
}
// The PageResponse contains modular content
// that the server wishes the client to display
// in the form of DivBoxes, Elements, and Links.
message PageResponse {
// divBoxes contains all of the divBoxes to be rendered for this page
DivBoxes divBoxes = 10;
// elements contains all of the non divBox elements to be rendered for this page
Elements elements = 11;
string name = 12; // the name of the page to be rendered
// a list of keystrokes that the client should honor, these could be
// of type link, formActivation, or divScroll
repeated KeyStroke keyStrokes = 13;
// any cookies that the server is requesting the client to set for future
// requests
repeated Cookie setCookies = 14;
// if the response is part of a stream then this is
// the time in milliseconds the client should wait
// before drawing the next request
int32 streamDelayMs = 15;
}
// Cookie loosly follows the cookie spec (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)
// but does not include protections for browser side code as today the uggly spec does not support
// client side code.
message Cookie {
string key = 10; // standard key or field name of cookie
string value = 11; // standard value of cookie
// the server which requested this cookie to be set.
// should be server only without including port
// e.g., "localhost" or "mysubdomain.domain.com"
string server = 12;
// private Cookies will never be sent back to server
bool private = 13;
// date when cookie expires relative to client in RFC1123 format.
// If improperly formatted will just be ignored and cookie will be treated as session cookie.
string expires = 14;
enum SameSite {
STRICT = 0; // cookie only sent to same site that set it
NONE = 1; // cookie can be sent cross site but only if Secure is set
}
// information on whether this cookie should only be sent to the server
// that requested it
SameSite sameSite = 15;
string page = 16; // if this cookie should only be sent back on specific pages
bool secure = 17; // if this cookie should only be sent when connection is secure
// indicates that this cookie should be sent in header metadata instead of body.
// This is useful if the server wants to pre-filter traffic, for example if a
//request is not authenticated it can avoid processing the full PageRequest
bool metadata = 18;
}
// A PageRequest contains the name of the
// desired page and some metadata about the
// cient height and width. The server can choose
// to ignore the width and height if it insists
// on statically sized content. Also, the server could
// generate a PageResponse saying something like
// "this server insists on a minimum height to view
// content" for example.
message PageRequest {
string name = 10; // The name of the page being requested
int32 clientWidth = 11; // The width of the client at the time of the request
int32 clientHeight = 12; // The height of the client at the time of the request
// data from form submissions or could be used to send generic key value pairs
repeated FormData formData = 13;
string server = 14; // the intended server for the request
string port = 15; // the intended port for the request
bool secure = 16; // whether or not the connection should be secure (TLS)
// Cookies that are intended to be sent from client to server
repeated Cookie sendCookies = 17;
bool stream = 18; // whether or not the request is for a page stream
}
// A FeedResponse is essentially a list of
// Pages that the server wishes to expose
// to the client. The server can obviously choose
// to hide some Pages or if it generates Pages
// dynamically it may not even be able to provide
// an accurate listing.
message FeedResponse {
repeated PageListing pages = 10;
string notes = 11; // reserved for future use
}
// A FeedRequest really needs no properties
// as it's just a call from the client for the
// server to send a Feed if it has one.
message FeedRequest {
bool sendData = 10; // reserved for future use
}
// Feed service can be implemented by the server
// and must provide a FeedResponse for a given FeedRequest.
// This is to be used as somewhat of a server index of
// available Pages when the server chooses to implement.
// It is strongly encouraged to implement a Feed because
// it makes for quality of life improvements for the client's
// user
service Feed {
rpc GetFeed(FeedRequest) returns(FeedResponse) {}
}
// In order for a server to serve any content it must
// implement the Page service which returns PageResponse
// for a given PageRequest
service Page {
rpc GetPage(PageRequest) returns(PageResponse) {}
rpc GetPageStream(PageRequest) returns (stream PageResponse) {}
}