@readme/cli 0.1.0 → 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/bin/readme.js +1 -1
- package/package.json +33 -24
- package/src/bootstrap.js +9 -13
- package/src/cli.js +17 -11
- package/src/commands/components.js +35 -18
- package/src/commands/dev.js +12 -8
- package/src/commands/eyes.js +12 -8
- package/src/commands/import.js +2190 -2048
- package/src/commands/lint.js +33 -29
- package/src/commands/oas-bundle.js +6 -2
- package/src/commands/oas-sync.js +96 -93
- package/src/commands/oas-validate.js +10 -7
- package/src/commands/pretty.js +177 -164
- package/src/commands/setup.js +24 -26
- package/src/commands/versions.js +6 -2
- package/src/dev/app/[...slug]/page.js +1 -0
- package/src/dev/app/layout.js +18 -11
- package/src/dev/app/page.js +1 -0
- package/src/dev/lib/docs.js +27 -19
- package/src/dev/next.config.mjs +2 -2
- package/src/gha.js +7 -7
- package/src/prompts/index.js +16 -6
- package/src/utils/eyes.js +143 -51
- package/src/utils/git.js +3 -3
- package/src/utils/lint.js +39 -38
- package/src/utils/llms.js +94 -91
- package/src/utils/markdown.js +256 -0
- package/src/utils/marketplace.js +12 -5
- package/src/utils/multi-spinner.js +5 -7
- package/src/utils/promise-pool.js +7 -5
- package/src/utils/reporter.js +88 -91
- package/src/utils/setup-templates.js +12 -6
- package/src/utils/styles.js +2 -1
- package/src/utils/tamagotchi.js +257 -91
- package/src/utils/tips.js +18 -9
- package/src/utils/url-segs.js +46 -41
- package/src/validators/components.js +55 -63
- package/src/validators/content.js +5 -10
- package/src/validators/duplicates.js +6 -2
- package/src/validators/frontmatter.js +19 -21
- package/src/validators/links.js +4 -8
- package/src/validators/oas-reference.js +7 -14
- package/src/validators/oas-schema.js +2 -0
- package/src/validators/ordering.js +5 -5
- package/src/validators/recipes.js +4 -12
- package/src/commands/import-oas.test.js +0 -277
- package/src/commands/import.classify.test.js +0 -172
- package/src/commands/import.landing.test.js +0 -217
- package/src/commands/import.slug-planner.test.js +0 -86
- package/src/commands/import.staging.test.js +0 -230
- package/src/commands/import.test.js +0 -382
- package/src/utils/llms.test.js +0 -302
- package/src/utils/url-segs.test.js +0 -239
package/src/dev/app/layout.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { collectSidebar } from '../lib/docs';
|
|
2
|
-
import { SidebarNav, SidebarPanel } from './Sidebar';
|
|
3
1
|
import '@readme/markdown/dist/main.css';
|
|
2
|
+
|
|
3
|
+
import { collectSidebar } from '../lib/docs';
|
|
4
|
+
|
|
4
5
|
import './globals.css';
|
|
6
|
+
import { SidebarNav, SidebarPanel } from './Sidebar';
|
|
5
7
|
|
|
6
8
|
export const metadata = {
|
|
7
9
|
title: {
|
|
@@ -21,10 +23,13 @@ export default async function RootLayout({ children }) {
|
|
|
21
23
|
</head>
|
|
22
24
|
<body className="bg-[#000343] text-gray-900 antialiased">
|
|
23
25
|
{/* Top Navigation */}
|
|
24
|
-
<header
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
<header
|
|
27
|
+
className="fixed top-0 inset-x-0 h-[48px] bg-[#000343] flex items-center px-5 z-50"
|
|
28
|
+
style={{
|
|
29
|
+
backgroundImage: `linear-gradient(rgba(255,255,255,0.08) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.08) 1px, transparent 1px)`,
|
|
30
|
+
backgroundSize: '20px 20px',
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
28
33
|
<div className="flex items-center gap-3 mr-8 shrink-0">
|
|
29
34
|
<div className="flex items-center gap-2">
|
|
30
35
|
<i className="fa-brands fa-readme text-[#018ef5] text-[18px] relative top-[1px]" />
|
|
@@ -50,17 +55,19 @@ export default async function RootLayout({ children }) {
|
|
|
50
55
|
|
|
51
56
|
{/* Content */}
|
|
52
57
|
<main className="ml-[300px] flex-1 min-w-0 bg-white rounded-tr-xl">
|
|
53
|
-
<div className="max-w-[820px] py-10 px-16">
|
|
54
|
-
{children}
|
|
55
|
-
</div>
|
|
58
|
+
<div className="max-w-[820px] py-10 px-16">{children}</div>
|
|
56
59
|
</main>
|
|
57
60
|
</div>
|
|
58
61
|
|
|
59
|
-
<style
|
|
62
|
+
<style
|
|
63
|
+
dangerouslySetInnerHTML={{
|
|
64
|
+
__html: `
|
|
60
65
|
[data-sidebar-group][data-expanded="false"] .sidebar-children { display: none; }
|
|
61
66
|
[data-sidebar-group][data-expanded="true"] .sidebar-children { display: block; }
|
|
62
67
|
[data-sidebar-group][data-expanded="true"] .sidebar-chevron { transform: rotate(90deg); }
|
|
63
|
-
|
|
68
|
+
`,
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
64
71
|
<script
|
|
65
72
|
dangerouslySetInnerHTML={{
|
|
66
73
|
__html: `(function(){var es=new EventSource('/__reload');es.onmessage=function(e){if(e.data==='reload')location.reload()};})();
|
package/src/dev/app/page.js
CHANGED
package/src/dev/lib/docs.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { createRequire } from 'node:module';
|
|
2
1
|
import fs from 'fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
import { compile, run } from '@readme/markdown';
|
|
6
|
-
import
|
|
6
|
+
import { load as loadYAML } from 'js-yaml';
|
|
7
|
+
|
|
8
|
+
import { parseFrontmatter } from '../../utils/markdown.js';
|
|
7
9
|
|
|
8
10
|
// Use createRequire to load react-dom/server at runtime,
|
|
9
11
|
// bypassing Next.js App Router's static import restriction.
|
|
@@ -36,7 +38,7 @@ function walkDir(dirPath, sectionDir, depth = 0) {
|
|
|
36
38
|
let order = [];
|
|
37
39
|
const orderPath = path.join(dirPath, '_order.yaml');
|
|
38
40
|
if (fs.existsSync(orderPath)) {
|
|
39
|
-
order =
|
|
41
|
+
order = loadYAML(fs.readFileSync(orderPath, 'utf-8')) || [];
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
// Get all items (exclude dotfiles and _-prefixed files)
|
|
@@ -90,16 +92,14 @@ function walkDir(dirPath, sectionDir, depth = 0) {
|
|
|
90
92
|
// If either exists, treat this as a clickable parent page.
|
|
91
93
|
const indexPath = path.join(dirPath, name, 'index.md');
|
|
92
94
|
const siblingMdPath = path.join(dirPath, `${name}.md`);
|
|
93
|
-
const parentPagePath = fs.existsSync(indexPath)
|
|
94
|
-
? indexPath
|
|
95
|
-
: fs.existsSync(siblingMdPath) ? siblingMdPath : null;
|
|
95
|
+
const parentPagePath = fs.existsSync(indexPath) ? indexPath : fs.existsSync(siblingMdPath) ? siblingMdPath : null;
|
|
96
96
|
|
|
97
97
|
let title = name;
|
|
98
98
|
let href = null;
|
|
99
99
|
let hidden = false;
|
|
100
100
|
let icon = null;
|
|
101
101
|
if (parentPagePath) {
|
|
102
|
-
const { data } =
|
|
102
|
+
const { data } = parseFrontmatter(fs.readFileSync(parentPagePath, 'utf-8'));
|
|
103
103
|
title = data.title || name;
|
|
104
104
|
href = `/${sectionDir}/${encodeURIComponent(name)}`;
|
|
105
105
|
hidden = !!data.hidden;
|
|
@@ -112,7 +112,7 @@ function walkDir(dirPath, sectionDir, depth = 0) {
|
|
|
112
112
|
mdFiles.delete(name);
|
|
113
113
|
} else if (isMd) {
|
|
114
114
|
const filePath = path.join(dirPath, `${name}.md`);
|
|
115
|
-
const { data } =
|
|
115
|
+
const { data } = parseFrontmatter(fs.readFileSync(filePath, 'utf-8'));
|
|
116
116
|
const linkUrl = data.link?.url;
|
|
117
117
|
entries.push({
|
|
118
118
|
title: data.title || name,
|
|
@@ -152,7 +152,7 @@ function loadCustomBlocks(docsRoot) {
|
|
|
152
152
|
|
|
153
153
|
for (const file of files) {
|
|
154
154
|
const raw = fs.readFileSync(path.join(blocksDir, file), 'utf-8');
|
|
155
|
-
const { data, content } =
|
|
155
|
+
const { data, content } = parseFrontmatter(raw);
|
|
156
156
|
const name = data.name || path.basename(file, path.extname(file));
|
|
157
157
|
sources[name] = content;
|
|
158
158
|
modules[name] = run(compile(content));
|
|
@@ -202,7 +202,7 @@ export function getPage(slugArray) {
|
|
|
202
202
|
if (!filePath) return null;
|
|
203
203
|
|
|
204
204
|
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
205
|
-
const { data, content } =
|
|
205
|
+
const { data, content } = parseFrontmatter(raw);
|
|
206
206
|
|
|
207
207
|
let html;
|
|
208
208
|
|
|
@@ -254,7 +254,7 @@ function renderOasOperationPreview(specFile, operationId) {
|
|
|
254
254
|
let spec;
|
|
255
255
|
try {
|
|
256
256
|
const rawSpec = fs.readFileSync(specPath, 'utf-8');
|
|
257
|
-
spec = specFile.toLowerCase().endsWith('.json') ? JSON.parse(rawSpec) :
|
|
257
|
+
spec = specFile.toLowerCase().endsWith('.json') ? JSON.parse(rawSpec) : loadYAML(rawSpec);
|
|
258
258
|
} catch (e) {
|
|
259
259
|
return `<p><em>Couldn't parse <code>reference/${specFile}</code>: ${escapeHtml(e.message)}</em></p>`;
|
|
260
260
|
}
|
|
@@ -272,16 +272,21 @@ function renderOasOperationPreview(specFile, operationId) {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
const { method, path: opPath, op } = found;
|
|
275
|
-
const methodColor =
|
|
276
|
-
|
|
277
|
-
|
|
275
|
+
const methodColor =
|
|
276
|
+
{
|
|
277
|
+
GET: '#22c55e',
|
|
278
|
+
POST: '#3b82f6',
|
|
279
|
+
PUT: '#f59e0b',
|
|
280
|
+
PATCH: '#a855f7',
|
|
281
|
+
DELETE: '#ef4444',
|
|
282
|
+
}[method] || '#6b7280';
|
|
278
283
|
|
|
279
284
|
const parts = [];
|
|
280
285
|
parts.push(
|
|
281
286
|
`<div style="display: flex; gap: 0.5rem; align-items: center; margin-bottom: 1rem;">` +
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
287
|
+
`<span style="background: ${methodColor}; color: white; padding: 0.15rem 0.5rem; border-radius: 0.25rem; font-family: monospace; font-weight: 600; font-size: 0.85rem;">${method}</span>` +
|
|
288
|
+
`<code style="font-size: 1rem;">${escapeHtml(opPath)}</code>` +
|
|
289
|
+
`</div>`,
|
|
285
290
|
);
|
|
286
291
|
if (op.description) parts.push(`<p>${escapeHtml(op.description)}</p>`);
|
|
287
292
|
|
|
@@ -317,7 +322,10 @@ function renderOasOperationPreview(specFile, operationId) {
|
|
|
317
322
|
}
|
|
318
323
|
|
|
319
324
|
function escapeHtml(s) {
|
|
320
|
-
return String(s).replace(
|
|
325
|
+
return String(s).replace(
|
|
326
|
+
/[&<>"']/g,
|
|
327
|
+
c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c],
|
|
328
|
+
);
|
|
321
329
|
}
|
|
322
330
|
|
|
323
331
|
function findFirstHref(items) {
|
package/src/dev/next.config.mjs
CHANGED
|
@@ -10,8 +10,8 @@ export default {
|
|
|
10
10
|
// Next's SWC loader excludes `node_modules` from JSX transformation by
|
|
11
11
|
// default. Marking our own package as a transpile target bypasses that.
|
|
12
12
|
transpilePackages: ['@readme/cli'],
|
|
13
|
-
serverExternalPackages: ['
|
|
14
|
-
webpack:
|
|
13
|
+
serverExternalPackages: ['js-yaml', '@readme/markdown'],
|
|
14
|
+
webpack: config => {
|
|
15
15
|
// Suppress noisy cache serialization warnings from large @readme/markdown bundle
|
|
16
16
|
config.infrastructureLogging = {
|
|
17
17
|
...config.infrastructureLogging,
|
package/src/gha.js
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
// let it do what it already does, exit code included.
|
|
18
18
|
|
|
19
19
|
import * as lint from './commands/lint.js';
|
|
20
|
-
import * as oasValidate from './commands/oas-validate.js';
|
|
21
20
|
import * as oasSync from './commands/oas-sync.js';
|
|
21
|
+
import * as oasValidate from './commands/oas-validate.js';
|
|
22
22
|
import { writeGithubActionsOutputs } from './utils/gha-output.js';
|
|
23
23
|
|
|
24
24
|
// Each command's run(options, cmd, ctx) only ever reads specific boolean
|
|
@@ -26,8 +26,8 @@ import { writeGithubActionsOutputs } from './utils/gha-output.js';
|
|
|
26
26
|
// (the commander Command instance normal CLI invocation would pass) — so a
|
|
27
27
|
// plain options object and a null cmd are enough here.
|
|
28
28
|
const COMMANDS = {
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
lint: { run: lint.run, flags: ['json', 'github', 'fix'] },
|
|
30
|
+
validate: { run: lint.run, flags: ['json', 'github', 'fix'] }, // alias, matches src/commands/lint.js
|
|
31
31
|
'oas:validate': { run: oasValidate.run, flags: ['dereference'] },
|
|
32
32
|
'oas:sync': { run: oasSync.run, flags: [] },
|
|
33
33
|
};
|
|
@@ -46,7 +46,7 @@ export async function run() {
|
|
|
46
46
|
if (!entry) {
|
|
47
47
|
console.error(
|
|
48
48
|
`::error::Unknown or unsupported command "${command || '(empty)'}" for the \`readme\` input. ` +
|
|
49
|
-
`Supported: ${[...new Set(Object.keys(COMMANDS).filter(
|
|
49
|
+
`Supported: ${[...new Set(Object.keys(COMMANDS).filter(k => k !== 'validate'))].join(', ')}.`,
|
|
50
50
|
);
|
|
51
51
|
writeGithubActionsOutputs({ 'has-errors': 'true' });
|
|
52
52
|
process.exit(1);
|
|
@@ -72,8 +72,8 @@ export async function run() {
|
|
|
72
72
|
|
|
73
73
|
if (badTokens.length > 0) {
|
|
74
74
|
console.error(
|
|
75
|
-
`::error::Unknown option${badTokens.length > 1 ? 's' : ''} ${badTokens.map(
|
|
76
|
-
`Supported: ${entry.flags.length > 0 ? entry.flags.map(
|
|
75
|
+
`::error::Unknown option${badTokens.length > 1 ? 's' : ''} ${badTokens.map(t => `"${t}"`).join(', ')} for "${command}". ` +
|
|
76
|
+
`Supported: ${entry.flags.length > 0 ? entry.flags.map(f => `--${f}`).join(', ') : '(none)'}.`,
|
|
77
77
|
);
|
|
78
78
|
writeGithubActionsOutputs({ 'has-errors': 'true' });
|
|
79
79
|
process.exit(1);
|
|
@@ -89,7 +89,7 @@ export async function run() {
|
|
|
89
89
|
await entry.run(options, null, { gitRoot });
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
run().catch(
|
|
92
|
+
run().catch(err => {
|
|
93
93
|
console.error(err);
|
|
94
94
|
// A thrown error (as opposed to a command's own controlled process.exit)
|
|
95
95
|
// means whatever run() was doing never reached its own
|
package/src/prompts/index.js
CHANGED
|
@@ -25,7 +25,7 @@ export const slotOrphansSystemPrompt = [
|
|
|
25
25
|
'Example output: {"assignments": [0, 2, 0, 1, -1, 3]}',
|
|
26
26
|
'',
|
|
27
27
|
'Guidance:',
|
|
28
|
-
|
|
28
|
+
"- Choose the best semantic fit based on the orphan's title and URL path.",
|
|
29
29
|
'- Only use -1 when no existing category is plausible.',
|
|
30
30
|
].join('\n');
|
|
31
31
|
|
|
@@ -54,13 +54,18 @@ export const slotOrphansOutputSchema = {
|
|
|
54
54
|
*/
|
|
55
55
|
export function buildSlotOrphansUserPrompt({ categories, orphans }) {
|
|
56
56
|
const catList = categories.map((c, i) => {
|
|
57
|
-
const sample = (c.pages || [])
|
|
57
|
+
const sample = (c.pages || [])
|
|
58
|
+
.slice(0, 3)
|
|
59
|
+
.map(p => p.title)
|
|
60
|
+
.join(', ');
|
|
58
61
|
return `${i}. ${c.title}${sample ? ` (e.g. ${sample})` : ''}`;
|
|
59
62
|
});
|
|
60
63
|
|
|
61
64
|
const orphanList = orphans.map((p, i) => {
|
|
62
65
|
let relPath = p.url;
|
|
63
|
-
try {
|
|
66
|
+
try {
|
|
67
|
+
relPath = new URL(p.url).pathname;
|
|
68
|
+
} catch {}
|
|
64
69
|
return `${i}. ${p.title} — ${relPath}`;
|
|
65
70
|
});
|
|
66
71
|
|
|
@@ -264,13 +269,17 @@ export const organizeFromScratchOutputSchema = {
|
|
|
264
269
|
export function buildOrganizeFromScratchUserPrompt({ siteTitle, items }) {
|
|
265
270
|
const compactLines = items.map((it, idx) => {
|
|
266
271
|
let relPath = it.url;
|
|
267
|
-
try {
|
|
272
|
+
try {
|
|
273
|
+
relPath = new URL(it.url).pathname + new URL(it.url).search;
|
|
274
|
+
} catch {}
|
|
268
275
|
return `${idx}\t${it.title}\t${relPath}`;
|
|
269
276
|
});
|
|
270
277
|
|
|
271
278
|
let origin = '(unknown)';
|
|
272
279
|
if (items.length > 0) {
|
|
273
|
-
try {
|
|
280
|
+
try {
|
|
281
|
+
origin = new URL(items[0].url).origin;
|
|
282
|
+
} catch {}
|
|
274
283
|
}
|
|
275
284
|
|
|
276
285
|
return [
|
|
@@ -507,7 +516,8 @@ export function prettifyPagePrompt(input) {
|
|
|
507
516
|
* @returns {string}
|
|
508
517
|
*/
|
|
509
518
|
export function stripCodeFences(text) {
|
|
510
|
-
return String(text)
|
|
519
|
+
return String(text)
|
|
520
|
+
.trim()
|
|
511
521
|
.replace(/^```json\s*/i, '')
|
|
512
522
|
.replace(/^```\s*/i, '')
|
|
513
523
|
.replace(/\s*```$/, '')
|
package/src/utils/eyes.js
CHANGED
|
@@ -19,7 +19,15 @@ export const palettes = {
|
|
|
19
19
|
red: { name: 'Red', body: '#EF4444', page: '#FFF5F5', pupil: '#7F1D1D', lid: '#FCA5A5' },
|
|
20
20
|
teal: { name: 'Teal', body: '#14B8A6', page: '#F0FFFE', pupil: '#134E4A', lid: '#5EEAD4' },
|
|
21
21
|
yellow: { name: 'Yellow', body: '#EAB308', page: '#FEFCE8', pupil: '#713F12', lid: '#FDE047' },
|
|
22
|
-
owl: {
|
|
22
|
+
owl: {
|
|
23
|
+
name: 'Owl',
|
|
24
|
+
body: '#8B5A2B',
|
|
25
|
+
page: '#FFF8EE',
|
|
26
|
+
pupil: '#2A1000',
|
|
27
|
+
lid: '#C4923A',
|
|
28
|
+
nose: '#FFD700',
|
|
29
|
+
hidden: true,
|
|
30
|
+
},
|
|
23
31
|
};
|
|
24
32
|
|
|
25
33
|
let currentPalette = palettes.blue;
|
|
@@ -124,7 +132,21 @@ function rebuildExpressions() {
|
|
|
124
132
|
|
|
125
133
|
export const animations = {
|
|
126
134
|
blink: {
|
|
127
|
-
frames: [
|
|
135
|
+
frames: [
|
|
136
|
+
'right',
|
|
137
|
+
'right',
|
|
138
|
+
'right',
|
|
139
|
+
'right',
|
|
140
|
+
'right',
|
|
141
|
+
'right',
|
|
142
|
+
'half-blink',
|
|
143
|
+
'squint',
|
|
144
|
+
'closed',
|
|
145
|
+
'closed',
|
|
146
|
+
'squint',
|
|
147
|
+
'half-blink',
|
|
148
|
+
'right',
|
|
149
|
+
],
|
|
128
150
|
durations: [1500, 100, 100, 100, 100, 100, 50, 50, 50, 80, 50, 50, 100],
|
|
129
151
|
},
|
|
130
152
|
|
|
@@ -134,85 +156,154 @@ export const animations = {
|
|
|
134
156
|
},
|
|
135
157
|
|
|
136
158
|
lookaround: {
|
|
137
|
-
frames: [
|
|
159
|
+
frames: [
|
|
160
|
+
'right',
|
|
161
|
+
'right',
|
|
162
|
+
'left',
|
|
163
|
+
'left',
|
|
164
|
+
'left',
|
|
165
|
+
'right',
|
|
166
|
+
'right',
|
|
167
|
+
'up-right',
|
|
168
|
+
'up-right',
|
|
169
|
+
'right',
|
|
170
|
+
'right',
|
|
171
|
+
'up-left',
|
|
172
|
+
'up-left',
|
|
173
|
+
'left',
|
|
174
|
+
'left',
|
|
175
|
+
'right',
|
|
176
|
+
],
|
|
138
177
|
durations: [600, 200, 120, 400, 200, 120, 400, 120, 400, 120, 200, 120, 400, 120, 200, 400],
|
|
139
178
|
},
|
|
140
179
|
|
|
141
180
|
'lookaround-blink': {
|
|
142
181
|
frames: [
|
|
143
|
-
'right',
|
|
144
|
-
'
|
|
145
|
-
'
|
|
146
|
-
'left',
|
|
147
|
-
'
|
|
148
|
-
'
|
|
149
|
-
'
|
|
150
|
-
'
|
|
151
|
-
'
|
|
182
|
+
'right',
|
|
183
|
+
'right',
|
|
184
|
+
'right',
|
|
185
|
+
'left',
|
|
186
|
+
'left',
|
|
187
|
+
'left',
|
|
188
|
+
'half-blink',
|
|
189
|
+
'squint',
|
|
190
|
+
'closed',
|
|
191
|
+
'closed',
|
|
192
|
+
'squint',
|
|
193
|
+
'half-blink',
|
|
194
|
+
'left',
|
|
195
|
+
'right',
|
|
196
|
+
'right',
|
|
197
|
+
'up-right',
|
|
198
|
+
'up-right',
|
|
199
|
+
'right',
|
|
200
|
+
'right',
|
|
201
|
+
'right',
|
|
202
|
+
'up-left',
|
|
203
|
+
'up-left',
|
|
204
|
+
'left',
|
|
205
|
+
'left',
|
|
206
|
+
'half-blink',
|
|
207
|
+
'squint',
|
|
208
|
+
'closed',
|
|
209
|
+
'closed',
|
|
210
|
+
'squint',
|
|
211
|
+
'half-blink',
|
|
212
|
+
'right',
|
|
213
|
+
'right',
|
|
152
214
|
],
|
|
153
215
|
durations: [
|
|
154
|
-
800, 200, 200,
|
|
155
|
-
|
|
156
|
-
50, 50, 50, 80, 50, 50,
|
|
157
|
-
200, 120, 400,
|
|
158
|
-
120, 500, 120,
|
|
159
|
-
200, 200,
|
|
160
|
-
120, 500, 120, 200,
|
|
161
|
-
50, 50, 50, 80, 50, 50,
|
|
162
|
-
120, 600,
|
|
216
|
+
800, 200, 200, 120, 400, 200, 50, 50, 50, 80, 50, 50, 200, 120, 400, 120, 500, 120, 200, 200, 120, 500, 120, 200,
|
|
217
|
+
50, 50, 50, 80, 50, 50, 120, 600,
|
|
163
218
|
],
|
|
164
219
|
},
|
|
165
220
|
|
|
166
221
|
all: {
|
|
167
222
|
frames: [
|
|
168
223
|
// idle, look around
|
|
169
|
-
'right',
|
|
170
|
-
'
|
|
171
|
-
'right',
|
|
224
|
+
'right',
|
|
225
|
+
'right',
|
|
226
|
+
'right',
|
|
227
|
+
'left',
|
|
228
|
+
'left',
|
|
229
|
+
'left',
|
|
230
|
+
'right',
|
|
231
|
+
'right',
|
|
172
232
|
// blink
|
|
173
|
-
'half-blink',
|
|
233
|
+
'half-blink',
|
|
234
|
+
'squint',
|
|
235
|
+
'closed',
|
|
236
|
+
'closed',
|
|
237
|
+
'squint',
|
|
238
|
+
'half-blink',
|
|
174
239
|
// look up + bounce
|
|
175
|
-
'right',
|
|
176
|
-
'
|
|
177
|
-
'
|
|
240
|
+
'right',
|
|
241
|
+
'right',
|
|
242
|
+
'up-right',
|
|
243
|
+
'up-right',
|
|
244
|
+
'right',
|
|
245
|
+
'right:up',
|
|
246
|
+
'right:up',
|
|
247
|
+
'right',
|
|
248
|
+
'right:up',
|
|
249
|
+
'right:up',
|
|
250
|
+
'right',
|
|
178
251
|
// look the other way
|
|
179
|
-
'right',
|
|
180
|
-
'
|
|
252
|
+
'right',
|
|
253
|
+
'left',
|
|
254
|
+
'left',
|
|
255
|
+
'up-left',
|
|
256
|
+
'up-left',
|
|
257
|
+
'left',
|
|
181
258
|
// blink
|
|
182
|
-
'half-blink',
|
|
259
|
+
'half-blink',
|
|
260
|
+
'squint',
|
|
261
|
+
'closed',
|
|
262
|
+
'closed',
|
|
263
|
+
'squint',
|
|
264
|
+
'half-blink',
|
|
183
265
|
// bounce
|
|
184
|
-
'left',
|
|
266
|
+
'left',
|
|
267
|
+
'left:up',
|
|
268
|
+
'left:up',
|
|
269
|
+
'left',
|
|
270
|
+
'left:up',
|
|
271
|
+
'left:up',
|
|
272
|
+
'left',
|
|
185
273
|
// settle back + bounce
|
|
186
|
-
'right',
|
|
187
|
-
'right
|
|
274
|
+
'right',
|
|
275
|
+
'right',
|
|
276
|
+
'right',
|
|
277
|
+
'right:up',
|
|
278
|
+
'right:up',
|
|
279
|
+
'right',
|
|
188
280
|
// blink
|
|
189
|
-
'half-blink',
|
|
190
|
-
'
|
|
281
|
+
'half-blink',
|
|
282
|
+
'squint',
|
|
283
|
+
'closed',
|
|
284
|
+
'closed',
|
|
285
|
+
'squint',
|
|
286
|
+
'half-blink',
|
|
287
|
+
'right',
|
|
288
|
+
'right',
|
|
191
289
|
],
|
|
192
290
|
durations: [
|
|
193
291
|
// idle, look around
|
|
194
|
-
800, 200, 200,
|
|
195
|
-
120, 400, 200,
|
|
196
|
-
120, 400,
|
|
292
|
+
800, 200, 200, 120, 400, 200, 120, 400,
|
|
197
293
|
// blink
|
|
198
294
|
50, 50, 50, 80, 50, 50,
|
|
199
295
|
// look up + bounce
|
|
200
|
-
200, 200,
|
|
201
|
-
120, 500, 120,
|
|
202
|
-
150, 150, 150, 150, 150, 200,
|
|
296
|
+
200, 200, 120, 500, 120, 150, 150, 150, 150, 150, 200,
|
|
203
297
|
// look the other way
|
|
204
|
-
300, 120, 400,
|
|
205
|
-
120, 500, 120,
|
|
298
|
+
300, 120, 400, 120, 500, 120,
|
|
206
299
|
// blink
|
|
207
300
|
50, 50, 50, 80, 50, 50,
|
|
208
301
|
// bounce
|
|
209
302
|
200, 150, 150, 150, 150, 150, 200,
|
|
210
303
|
// settle back + bounce
|
|
211
|
-
120, 200, 300,
|
|
212
|
-
150, 150, 200,
|
|
304
|
+
120, 200, 300, 150, 150, 200,
|
|
213
305
|
// blink
|
|
214
|
-
50, 50, 50, 80, 50, 50,
|
|
215
|
-
200, 800,
|
|
306
|
+
50, 50, 50, 80, 50, 50, 200, 800,
|
|
216
307
|
],
|
|
217
308
|
},
|
|
218
309
|
};
|
|
@@ -253,7 +344,7 @@ export function header(opts = {}) {
|
|
|
253
344
|
const icon = eyes(expression);
|
|
254
345
|
const gap = ' ';
|
|
255
346
|
|
|
256
|
-
const title = chalk.bold.hex(currentPalette.body)('The ReadMe CLI') + (version ?
|
|
347
|
+
const title = chalk.bold.hex(currentPalette.body)('The ReadMe CLI') + (version ? ` ${chalk.dim(`v${version}`)}` : '');
|
|
257
348
|
const bin = binName ? chalk.white(binName) : '';
|
|
258
349
|
const greetLine = greeting ? chalk.dim(greeting) : '';
|
|
259
350
|
|
|
@@ -296,7 +387,8 @@ export function animate(name, opts = {}) {
|
|
|
296
387
|
const headerLines = [];
|
|
297
388
|
if (version || bin) {
|
|
298
389
|
const gap = ' ';
|
|
299
|
-
headerLines[0] =
|
|
390
|
+
headerLines[0] =
|
|
391
|
+
gap + chalk.bold.hex(currentPalette.body)('The ReadMe CLI') + (version ? ` ${chalk.dim(`v${version}`)}` : '');
|
|
300
392
|
headerLines[1] = gap + (bin ? chalk.white(bin) : '');
|
|
301
393
|
if (subtitle) headerLines[2] = gap + subtitle;
|
|
302
394
|
}
|
|
@@ -340,7 +432,7 @@ export function animate(name, opts = {}) {
|
|
|
340
432
|
firstDraw = false;
|
|
341
433
|
|
|
342
434
|
for (const line of lines) {
|
|
343
|
-
process.stdout.write(indent + line
|
|
435
|
+
process.stdout.write(`${indent + line}\n`);
|
|
344
436
|
}
|
|
345
437
|
|
|
346
438
|
const duration = anim.durations[i % anim.durations.length];
|
package/src/utils/git.js
CHANGED
|
@@ -63,10 +63,10 @@ export function detectRemotePlatform() {
|
|
|
63
63
|
const remotes = readRemotes();
|
|
64
64
|
if (!remotes) return null;
|
|
65
65
|
for (const [key, def] of Object.entries(PLATFORMS)) {
|
|
66
|
-
if (def.remoteHosts && def.remoteHosts.some(
|
|
66
|
+
if (def.remoteHosts && def.remoteHosts.some(h => remotes.toLowerCase().includes(h))) {
|
|
67
67
|
return key;
|
|
68
68
|
}
|
|
69
|
-
if (def.remotePathHints && def.remotePathHints.some(
|
|
69
|
+
if (def.remotePathHints && def.remotePathHints.some(p => remotes.toLowerCase().includes(p))) {
|
|
70
70
|
return key;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
@@ -81,7 +81,7 @@ export function detectExistingCi(gitRoot) {
|
|
|
81
81
|
if (!gitRoot) return [];
|
|
82
82
|
const found = [];
|
|
83
83
|
for (const [key, def] of Object.entries(PLATFORMS)) {
|
|
84
|
-
const hit = def.fsMarkers.some(
|
|
84
|
+
const hit = def.fsMarkers.some(marker => fs.existsSync(path.join(gitRoot, marker)));
|
|
85
85
|
if (hit) found.push(key);
|
|
86
86
|
}
|
|
87
87
|
return found;
|