innernote 0.1.2 → 0.2.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/dist/index.js +164 -98
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -286,44 +286,44 @@ function wordmark(name, gap = 1) {
|
|
|
286
286
|
function widest(rows) {
|
|
287
287
|
return Math.max(...rows.map((r) => r.length));
|
|
288
288
|
}
|
|
289
|
-
function lockup(name = "innernote",
|
|
290
|
-
const room = (process.stdout.columns
|
|
291
|
-
const
|
|
292
|
-
const
|
|
289
|
+
function lockup(name = "innernote", sub) {
|
|
290
|
+
const room = (process.stdout.columns || 80) - 5;
|
|
291
|
+
const subs = sub == null ? [] : Array.isArray(sub) ? sub : [sub];
|
|
292
|
+
const mark = logo(2).map((r) => r.trimEnd());
|
|
293
|
+
const ink = widest(mark);
|
|
293
294
|
const word = wordmark(name);
|
|
294
295
|
if (word) {
|
|
295
|
-
const
|
|
296
|
-
|
|
296
|
+
const gap = 2;
|
|
297
|
+
const wide = Math.max(widest(word), ...subs.map((s) => width(s)));
|
|
298
|
+
if (ink + gap + wide <= room) {
|
|
297
299
|
const rows2 = mark.map((r, i) => {
|
|
298
300
|
const right = word[i] ?? "";
|
|
299
|
-
return right ? `${caramel(r.padEnd(
|
|
301
|
+
return right ? `${caramel(r.padEnd(ink))}${" ".repeat(gap)}${bold2(caramel(right))}` : caramel(r);
|
|
300
302
|
});
|
|
301
|
-
|
|
302
|
-
|
|
303
|
+
const indent = " ".repeat(ink + gap);
|
|
304
|
+
for (const line of subs)
|
|
305
|
+
rows2.push(`${indent}${line}`);
|
|
303
306
|
return rows2;
|
|
304
307
|
}
|
|
305
308
|
}
|
|
306
|
-
const
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (
|
|
315
|
-
return left +
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
rows
|
|
321
|
-
if (tagline)
|
|
322
|
-
rows.push(dim2(tagline));
|
|
323
|
-
return rows;
|
|
309
|
+
const mid = Math.floor(mark.length / 2);
|
|
310
|
+
const below = [];
|
|
311
|
+
const rows = mark.map((r, i) => {
|
|
312
|
+
const left = caramel(r.padEnd(ink)) + " ";
|
|
313
|
+
if (i === mid)
|
|
314
|
+
return left + bold2(caramel(name));
|
|
315
|
+
const sub2 = subs[i - mid - 1];
|
|
316
|
+
if (i > mid && sub2 !== undefined) {
|
|
317
|
+
if (ink + 3 + width(sub2) <= room)
|
|
318
|
+
return left + sub2;
|
|
319
|
+
below.push(sub2);
|
|
320
|
+
}
|
|
321
|
+
return caramel(r);
|
|
322
|
+
});
|
|
323
|
+
return [...rows, ...below];
|
|
324
324
|
}
|
|
325
325
|
function banner(tagline = "your voice, from the terminal") {
|
|
326
|
-
return lockup("innernote", tagline).map((r) => " " + r).join(`
|
|
326
|
+
return lockup("innernote", dim2(tagline)).map((r) => " " + r).join(`
|
|
327
327
|
`);
|
|
328
328
|
}
|
|
329
329
|
function bar(score, width2 = 10) {
|
|
@@ -1122,6 +1122,9 @@ var dim4 = sgr2("2");
|
|
|
1122
1122
|
var green4 = sgr2("32");
|
|
1123
1123
|
var yellow4 = sgr2("33");
|
|
1124
1124
|
var red4 = sgr2("31");
|
|
1125
|
+
function width2(s) {
|
|
1126
|
+
return s.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
1127
|
+
}
|
|
1125
1128
|
var canAnimate2 = isTTY2 && process.env.TERM !== "dumb" && !process.env.CI;
|
|
1126
1129
|
var MARK_GRID2 = [
|
|
1127
1130
|
"....#....",
|
|
@@ -1160,44 +1163,44 @@ function wordmark2(name, gap = 1) {
|
|
|
1160
1163
|
function widest2(rows) {
|
|
1161
1164
|
return Math.max(...rows.map((r) => r.length));
|
|
1162
1165
|
}
|
|
1163
|
-
function lockup2(name = "innernote",
|
|
1164
|
-
const room = (process.stdout.columns
|
|
1165
|
-
const
|
|
1166
|
-
const
|
|
1166
|
+
function lockup2(name = "innernote", sub) {
|
|
1167
|
+
const room = (process.stdout.columns || 80) - 5;
|
|
1168
|
+
const subs = sub == null ? [] : Array.isArray(sub) ? sub : [sub];
|
|
1169
|
+
const mark = logo2(2).map((r) => r.trimEnd());
|
|
1170
|
+
const ink = widest2(mark);
|
|
1167
1171
|
const word = wordmark2(name);
|
|
1168
1172
|
if (word) {
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1173
|
+
const gap = 2;
|
|
1174
|
+
const wide = Math.max(widest2(word), ...subs.map((s) => width2(s)));
|
|
1175
|
+
if (ink + gap + wide <= room) {
|
|
1171
1176
|
const rows2 = mark.map((r, i) => {
|
|
1172
1177
|
const right = word[i] ?? "";
|
|
1173
|
-
return right ? `${caramel2(r.padEnd(
|
|
1178
|
+
return right ? `${caramel2(r.padEnd(ink))}${" ".repeat(gap)}${bold4(caramel2(right))}` : caramel2(r);
|
|
1174
1179
|
});
|
|
1175
|
-
|
|
1176
|
-
|
|
1180
|
+
const indent = " ".repeat(ink + gap);
|
|
1181
|
+
for (const line of subs)
|
|
1182
|
+
rows2.push(`${indent}${line}`);
|
|
1177
1183
|
return rows2;
|
|
1178
1184
|
}
|
|
1179
1185
|
}
|
|
1180
|
-
const
|
|
1181
|
-
const
|
|
1182
|
-
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
if (
|
|
1189
|
-
return left +
|
|
1190
|
-
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
rows
|
|
1195
|
-
if (tagline)
|
|
1196
|
-
rows.push(dim4(tagline));
|
|
1197
|
-
return rows;
|
|
1186
|
+
const mid = Math.floor(mark.length / 2);
|
|
1187
|
+
const below = [];
|
|
1188
|
+
const rows = mark.map((r, i) => {
|
|
1189
|
+
const left = caramel2(r.padEnd(ink)) + " ";
|
|
1190
|
+
if (i === mid)
|
|
1191
|
+
return left + bold4(caramel2(name));
|
|
1192
|
+
const sub2 = subs[i - mid - 1];
|
|
1193
|
+
if (i > mid && sub2 !== undefined) {
|
|
1194
|
+
if (ink + 3 + width2(sub2) <= room)
|
|
1195
|
+
return left + sub2;
|
|
1196
|
+
below.push(sub2);
|
|
1197
|
+
}
|
|
1198
|
+
return caramel2(r);
|
|
1199
|
+
});
|
|
1200
|
+
return [...rows, ...below];
|
|
1198
1201
|
}
|
|
1199
1202
|
function banner2(tagline = "your voice, from the terminal") {
|
|
1200
|
-
return lockup2("innernote", tagline).map((r) => " " + r).join(`
|
|
1203
|
+
return lockup2("innernote", dim4(tagline)).map((r) => " " + r).join(`
|
|
1201
1204
|
`);
|
|
1202
1205
|
}
|
|
1203
1206
|
|
|
@@ -1342,12 +1345,12 @@ function commandHelp(name) {
|
|
|
1342
1345
|
return lines.join(`
|
|
1343
1346
|
`);
|
|
1344
1347
|
}
|
|
1345
|
-
function wrap3(text,
|
|
1348
|
+
function wrap3(text, width3, indent) {
|
|
1346
1349
|
const words = text.split(/\s+/);
|
|
1347
1350
|
const lines = [];
|
|
1348
1351
|
let line = "";
|
|
1349
1352
|
for (const w of words) {
|
|
1350
|
-
if ((line + " " + w).trim().length >
|
|
1353
|
+
if ((line + " " + w).trim().length > width3) {
|
|
1351
1354
|
lines.push(indent + line.trim());
|
|
1352
1355
|
line = w;
|
|
1353
1356
|
} else {
|
|
@@ -1369,67 +1372,68 @@ function margin(rows) {
|
|
|
1369
1372
|
`);
|
|
1370
1373
|
}
|
|
1371
1374
|
function landing(state) {
|
|
1372
|
-
const
|
|
1373
|
-
if (state.
|
|
1374
|
-
|
|
1375
|
-
}
|
|
1376
|
-
const sub = [];
|
|
1375
|
+
const small = [];
|
|
1376
|
+
if (state.plan)
|
|
1377
|
+
small.push(state.plan);
|
|
1377
1378
|
if (state.powers)
|
|
1378
|
-
|
|
1379
|
-
if (typeof state.expiresInDays === "number" && state.expiresInDays <= 14) {
|
|
1380
|
-
sub.push(`key expires in ${state.expiresInDays} ${state.expiresInDays === 1 ? "day" : "days"}`);
|
|
1381
|
-
}
|
|
1379
|
+
small.push(state.powers);
|
|
1382
1380
|
if (state.version)
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1381
|
+
small.push(`v${state.version}`);
|
|
1382
|
+
const sub = [];
|
|
1383
|
+
if (state.name)
|
|
1384
|
+
sub.push(`${bold2(state.name)} ${dim2(small.join(" "))}`);
|
|
1385
|
+
else if (small.length)
|
|
1386
|
+
sub.push(dim2(small.join(" ")));
|
|
1387
|
+
if (typeof state.expiresInDays === "number" && state.expiresInDays <= 14) {
|
|
1388
|
+
sub.push(yellow2(`key expires in ${state.expiresInDays} ${state.expiresInDays === 1 ? "day" : "days"}`));
|
|
1388
1389
|
}
|
|
1390
|
+
const rows = ["", ...lockup("innernote", sub), ""];
|
|
1391
|
+
if (state.week?.length)
|
|
1392
|
+
rows.push(...state.week, "");
|
|
1389
1393
|
const counts = [];
|
|
1390
1394
|
if (state.ideas)
|
|
1391
1395
|
counts.push(`${state.ideas} ${state.ideas === 1 ? "idea" : "ideas"} waiting`);
|
|
1392
1396
|
if (state.drafts)
|
|
1393
|
-
counts.push(`${state.drafts} drafts`);
|
|
1397
|
+
counts.push(`${state.drafts} ${state.drafts === 1 ? "draft" : "drafts"}`);
|
|
1394
1398
|
if (counts.length)
|
|
1395
|
-
rows.push(
|
|
1399
|
+
rows.push(dim2(counts.join(" ")));
|
|
1396
1400
|
if (state.next) {
|
|
1397
|
-
rows.push(
|
|
1401
|
+
rows.push(`${caramel(state.next.command)} ${dim2(state.next.why)}`);
|
|
1398
1402
|
}
|
|
1399
1403
|
rows.push("");
|
|
1400
1404
|
return margin(rows);
|
|
1401
1405
|
}
|
|
1402
1406
|
function landingDisconnected(apiUrl, version) {
|
|
1407
|
+
const host = apiUrl.replace(/^https?:\/\//, "");
|
|
1408
|
+
const sub = [dim2("LinkedIn posts in your voice, from the terminal")];
|
|
1409
|
+
if (version)
|
|
1410
|
+
sub.push(dim2(`v${version}`));
|
|
1403
1411
|
return margin([
|
|
1404
1412
|
"",
|
|
1405
|
-
...lockup("innernote",
|
|
1406
|
-
...version ? [` ${dim2(`v${version}`)}`] : [],
|
|
1407
|
-
"",
|
|
1408
|
-
dim2("Write LinkedIn posts in your voice, without leaving here."),
|
|
1409
|
-
"",
|
|
1410
|
-
`${caramel(`${CMD} login`)}${pad("", Math.max(3, 20 - width(`${CMD} login`)))}${dim2("connect this machine")}`,
|
|
1411
|
-
dim2(`Get a code at ${apiUrl.replace(/^https?:\/\//, "")}/dashboard/settings`),
|
|
1413
|
+
...lockup("innernote", sub),
|
|
1412
1414
|
"",
|
|
1413
|
-
`${
|
|
1415
|
+
`${caramel(`${CMD} login`)} ${dim2("connect this machine")}`,
|
|
1416
|
+
dim2(`Get a code at ${host}/dashboard/settings`),
|
|
1417
|
+
`${dim2("No account yet?")} ${caramel(host)}`,
|
|
1414
1418
|
""
|
|
1415
1419
|
]);
|
|
1416
1420
|
}
|
|
1417
1421
|
function suggest(state) {
|
|
1418
1422
|
if (state.scheduled === 0 && state.ideas > 0) {
|
|
1419
|
-
return { command:
|
|
1423
|
+
return { command: "ideas", why: "nothing scheduled, and you have things saved" };
|
|
1420
1424
|
}
|
|
1421
1425
|
if (state.scheduled === 0) {
|
|
1422
|
-
return { command:
|
|
1426
|
+
return { command: "write", why: "the week is empty" };
|
|
1423
1427
|
}
|
|
1424
1428
|
if (state.ideas >= 5) {
|
|
1425
|
-
return { command:
|
|
1429
|
+
return { command: "ideas", why: "your inbox is filling up" };
|
|
1426
1430
|
}
|
|
1427
|
-
return { command:
|
|
1431
|
+
return { command: "write", why: "start something" };
|
|
1428
1432
|
}
|
|
1429
1433
|
// package.json
|
|
1430
1434
|
var package_default = {
|
|
1431
1435
|
name: "innernote",
|
|
1432
|
-
version: "0.
|
|
1436
|
+
version: "0.2.0",
|
|
1433
1437
|
description: "Write LinkedIn posts in your voice, from the terminal.",
|
|
1434
1438
|
type: "module",
|
|
1435
1439
|
bin: {
|
|
@@ -1466,7 +1470,7 @@ function powers2(scopes) {
|
|
|
1466
1470
|
return scopes[0];
|
|
1467
1471
|
return `${scopes.slice(0, -1).join(", ")} and ${scopes[scopes.length - 1]}`;
|
|
1468
1472
|
}
|
|
1469
|
-
async function home() {
|
|
1473
|
+
async function home(inSession = false) {
|
|
1470
1474
|
const config = await loadConfig();
|
|
1471
1475
|
if (!config.token) {
|
|
1472
1476
|
out();
|
|
@@ -1498,11 +1502,14 @@ async function home() {
|
|
|
1498
1502
|
`).map((l) => l.replace(/^ {2}/, "")) : null,
|
|
1499
1503
|
ideas: ideas2?.ideas.length,
|
|
1500
1504
|
drafts: drafts2?.posts.length,
|
|
1501
|
-
next:
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1505
|
+
next: (() => {
|
|
1506
|
+
const n = suggest({
|
|
1507
|
+
scheduled,
|
|
1508
|
+
ideas: ideas2?.ideas.length ?? 0,
|
|
1509
|
+
drafts: drafts2?.posts.length ?? 0
|
|
1510
|
+
});
|
|
1511
|
+
return inSession ? n : { ...n, command: `${CMD} ${n.command}` };
|
|
1512
|
+
})()
|
|
1506
1513
|
}));
|
|
1507
1514
|
out();
|
|
1508
1515
|
return 0;
|
|
@@ -1511,6 +1518,30 @@ async function home() {
|
|
|
1511
1518
|
// src/session.ts
|
|
1512
1519
|
import { createInterface } from "node:readline";
|
|
1513
1520
|
|
|
1521
|
+
// src/ghost.ts
|
|
1522
|
+
function ghostFor(line2, cursor, history, names) {
|
|
1523
|
+
if (!line2 || cursor !== line2.length)
|
|
1524
|
+
return null;
|
|
1525
|
+
if (line2.startsWith(" "))
|
|
1526
|
+
return null;
|
|
1527
|
+
const fromHistory = history.find((h) => h.startsWith(line2) && h.length > line2.length);
|
|
1528
|
+
if (fromHistory)
|
|
1529
|
+
return fromHistory.slice(line2.length);
|
|
1530
|
+
if (!line2.includes(" ")) {
|
|
1531
|
+
const name = names.find((n) => n.startsWith(line2) && n.length > line2.length);
|
|
1532
|
+
return name ? name.slice(line2.length) : null;
|
|
1533
|
+
}
|
|
1534
|
+
if (line2.startsWith("help ")) {
|
|
1535
|
+
const arg = line2.slice(5);
|
|
1536
|
+
if (arg && !arg.includes(" ")) {
|
|
1537
|
+
const name = names.find((n) => n.startsWith(arg) && n.length > arg.length);
|
|
1538
|
+
if (name)
|
|
1539
|
+
return name.slice(arg.length);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
return null;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1514
1545
|
// src/help.ts
|
|
1515
1546
|
var COMMANDS2 = {
|
|
1516
1547
|
login: {
|
|
@@ -1652,12 +1683,12 @@ function commandHelp2(name) {
|
|
|
1652
1683
|
return lines.join(`
|
|
1653
1684
|
`);
|
|
1654
1685
|
}
|
|
1655
|
-
function wrap4(text,
|
|
1686
|
+
function wrap4(text, width3, indent) {
|
|
1656
1687
|
const words = text.split(/\s+/);
|
|
1657
1688
|
const lines = [];
|
|
1658
1689
|
let line2 = "";
|
|
1659
1690
|
for (const w of words) {
|
|
1660
|
-
if ((line2 + " " + w).trim().length >
|
|
1691
|
+
if ((line2 + " " + w).trim().length > width3) {
|
|
1661
1692
|
lines.push(indent + line2.trim());
|
|
1662
1693
|
line2 = w;
|
|
1663
1694
|
} else {
|
|
@@ -1729,6 +1760,40 @@ function indented(run) {
|
|
|
1729
1760
|
};
|
|
1730
1761
|
return run().finally(restore);
|
|
1731
1762
|
}
|
|
1763
|
+
function armGhost(rl, names, promptWidth) {
|
|
1764
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
1765
|
+
return;
|
|
1766
|
+
if (dim2("x") === "x")
|
|
1767
|
+
return;
|
|
1768
|
+
const inner = rl;
|
|
1769
|
+
let shown = null;
|
|
1770
|
+
const clear = () => {
|
|
1771
|
+
if (shown == null)
|
|
1772
|
+
return;
|
|
1773
|
+
process.stdout.write("\x1B[K");
|
|
1774
|
+
shown = null;
|
|
1775
|
+
};
|
|
1776
|
+
const draw = () => {
|
|
1777
|
+
if (process.stdin.isPaused())
|
|
1778
|
+
return;
|
|
1779
|
+
const rest = ghostFor(inner.line ?? "", inner.cursor ?? 0, inner.history ?? [], names);
|
|
1780
|
+
if (!rest)
|
|
1781
|
+
return;
|
|
1782
|
+
const cols = process.stdout.columns || 80;
|
|
1783
|
+
if (promptWidth() + (inner.line?.length ?? 0) + rest.length >= cols - 1)
|
|
1784
|
+
return;
|
|
1785
|
+
process.stdout.write(`${dim2(rest)}\x1B[${rest.length}D`);
|
|
1786
|
+
shown = rest;
|
|
1787
|
+
};
|
|
1788
|
+
process.stdin.prependListener("keypress", (_ch, key) => {
|
|
1789
|
+
const offered = shown;
|
|
1790
|
+
clear();
|
|
1791
|
+
if (key?.name === "right" && offered && inner.cursor === inner.line.length) {
|
|
1792
|
+
rl.write(offered);
|
|
1793
|
+
}
|
|
1794
|
+
setImmediate(draw);
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1732
1797
|
async function session(opts) {
|
|
1733
1798
|
await opts.intro();
|
|
1734
1799
|
const names = [...Object.keys(COMMANDS2), ...BUILTINS];
|
|
@@ -1746,7 +1811,8 @@ async function session(opts) {
|
|
|
1746
1811
|
return [hits.length ? hits : names, line2];
|
|
1747
1812
|
}
|
|
1748
1813
|
});
|
|
1749
|
-
|
|
1814
|
+
armGhost(rl, names, () => width(promptFor()));
|
|
1815
|
+
console.log(` ${dim2("Type a command, or")} ${caramel("help")}${dim2(". Right arrow takes the hint. Ctrl-C twice to leave.")}
|
|
1750
1816
|
`);
|
|
1751
1817
|
rl.prompt();
|
|
1752
1818
|
return new Promise((resolve) => {
|
|
@@ -1927,7 +1993,7 @@ async function main() {
|
|
|
1927
1993
|
return home();
|
|
1928
1994
|
return session({
|
|
1929
1995
|
intro: async () => {
|
|
1930
|
-
await home();
|
|
1996
|
+
await home(true);
|
|
1931
1997
|
},
|
|
1932
1998
|
status: () => {
|
|
1933
1999
|
const d = getDraft2();
|