@khanglvm/relay 0.6.0 → 0.8.0

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/src/ui/blocks.js CHANGED
@@ -103,6 +103,55 @@
103
103
  return out;
104
104
  }
105
105
 
106
+ // GFM pipe tables — a header row of "| a | b |" cells immediately followed
107
+ // by a separator row of dashes (with optional ":" alignment markers).
108
+ // Rendered as a real .blk-table so it matches the dedicated table block.
109
+ function splitRow(row) {
110
+ const trimmed = row.trim().replace(/^\|/, '').replace(/\|$/, '');
111
+ return trimmed.split(/(?<!\\)\|/).map((c) => c.replace(/\\\|/g, '|').trim());
112
+ }
113
+ function isSepRow(row) {
114
+ if (!row || row.indexOf('|') === -1) return false;
115
+ const cells = splitRow(row);
116
+ return cells.length > 0 && cells.every((c) => /^:?-{1,}:?$/.test(c));
117
+ }
118
+ function isTableStart(idx) {
119
+ const head = lines[idx];
120
+ return (
121
+ idx + 1 < lines.length &&
122
+ head.indexOf('|') !== -1 &&
123
+ !isSepRow(head) &&
124
+ isSepRow(lines[idx + 1])
125
+ );
126
+ }
127
+ function consumeTable() {
128
+ const headers = splitRow(lines[i]);
129
+ const aligns = splitRow(lines[i + 1]).map((c) => {
130
+ const left = c.startsWith(':');
131
+ const right = c.endsWith(':');
132
+ return left && right ? 'center' : right ? 'right' : left ? 'left' : '';
133
+ });
134
+ i += 2;
135
+ const body = [];
136
+ while (i < lines.length && !/^\s*$/.test(lines[i]) && lines[i].indexOf('|') !== -1 && !isSepRow(lines[i])) {
137
+ body.push(splitRow(lines[i]));
138
+ i++;
139
+ }
140
+ const ncols = headers.length;
141
+ const alignAttr = (ci) => (aligns[ci] ? ` style="text-align:${aligns[ci]}"` : '');
142
+ const cell = (tag, ci, text) => `<${tag}${alignAttr(ci)}>${mdInline(esc(text == null ? '' : text))}</${tag}>`;
143
+ let out = '<div class="md-tablewrap"><table class="blk-table md-table"><thead><tr>';
144
+ for (let c = 0; c < ncols; c++) out += cell('th', c, headers[c]);
145
+ out += '</tr></thead><tbody>';
146
+ for (const r of body) {
147
+ out += '<tr>';
148
+ for (let c = 0; c < ncols; c++) out += cell('td', c, r[c]);
149
+ out += '</tr>';
150
+ }
151
+ out += '</tbody></table></div>';
152
+ return out;
153
+ }
154
+
106
155
  while (i < lines.length) {
107
156
  const line = lines[i];
108
157
 
@@ -140,6 +189,9 @@
140
189
  continue;
141
190
  }
142
191
 
192
+ // GFM pipe table (header row + dash separator)
193
+ if (isTableStart(i)) { html += consumeTable(); continue; }
194
+
143
195
  // lists
144
196
  if (/^(\s*)([-*]|\d+\.)\s+/.test(line)) { html += consumeList(); continue; }
145
197
 
@@ -155,7 +207,8 @@
155
207
  !/^\s*---+\s*$/.test(lines[i]) &&
156
208
  !/^#{1,3}\s+/.test(lines[i]) &&
157
209
  !/^\s*>\s?/.test(lines[i]) &&
158
- !/^(\s*)([-*]|\d+\.)\s+/.test(lines[i])
210
+ !/^(\s*)([-*]|\d+\.)\s+/.test(lines[i]) &&
211
+ !isTableStart(i)
159
212
  ) {
160
213
  buf.push(lines[i]);
161
214
  i++;
package/src/ui/style.css CHANGED
@@ -73,7 +73,7 @@ body {
73
73
  color: var(--fg);
74
74
  font: 16px/1.6 var(--sans);
75
75
  -webkit-font-smoothing: antialiased;
76
- transition: background 200ms var(--ease), color 200ms var(--ease);
76
+ transition: background 200ms var(--ease), color 200ms var(--ease), padding 240ms var(--ease);
77
77
  }
78
78
  .wrap { max-width: 860px; margin: 0 auto; padding: 32px 20px 28px; }
79
79
 
@@ -193,7 +193,7 @@ input[type="text"]:focus, textarea:focus {
193
193
  textarea { min-height: 90px; resize: vertical; }
194
194
 
195
195
  .qnotewrap { margin-top: 10px; }
196
- .qnotewrap .qnote { font-size: 0.88rem; padding: 8px 12px; }
196
+ .qnotewrap .qnote { font-size: 0.88rem; padding: 8px 12px; min-height: 52px; resize: vertical; }
197
197
 
198
198
  .errmsg { color: var(--danger); font-size: 0.85rem; margin: 8px 0 0; display: none; }
199
199
  .card.error .errmsg { display: block; }
@@ -220,8 +220,14 @@ textarea { min-height: 90px; resize: vertical; }
220
220
  position: sticky; top: 0;
221
221
  background: var(--danger); color: var(--danger-fg);
222
222
  text-align: center; padding: 9px 16px; font-size: 0.9rem;
223
+ line-height: 1.45;
223
224
  z-index: 10; display: none;
225
+ border-bottom: 1px solid transparent;
224
226
  }
227
+ /* Calm status notes (timeout hand-back / lost connection). Never the red error
228
+ state — the board stays usable, so these only inform. */
229
+ .banner.info { background: var(--accent-soft); color: var(--accent); }
230
+ .banner.warn { background: var(--bg-sunken); color: var(--fg-2); border-bottom-color: var(--border-strong); }
225
231
 
226
232
  /* Live-update toast: flagged after a `rly update` reload (see app.js).
227
233
  Fixed top-center, accent-soft bg, accent text; JS auto-removes it. */