create-thally-docs 0.8.0 → 0.8.1
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/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# create-thally-docs
|
|
2
2
|
|
|
3
|
-
Scaffold
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Scaffold the first customer-facing knowledge surface in a
|
|
4
|
+
[Thally](https://github.com/thallylabs/thally) product-knowledge pipeline. The
|
|
5
|
+
result is an open documentation site that serves every page to humans as
|
|
6
|
+
polished HTML and to agents as structured JSON, JSON-LD, and Markdown from the
|
|
7
|
+
same URL.
|
|
6
8
|
|
|
7
9
|
## Quick start
|
|
8
10
|
|
|
@@ -45,9 +47,14 @@ interactive question explicitly.
|
|
|
45
47
|
| `create-thally-docs translate --locale <code>` | Translate content into another locale |
|
|
46
48
|
|
|
47
49
|
Interactive migrations ask whether the source is Mintlify, Docusaurus, or
|
|
48
|
-
another auto-detected platform.
|
|
50
|
+
another auto-detected platform. When automatic detection receives a live
|
|
51
|
+
website URL, the CLI recommends its source GitHub repository and requires
|
|
52
|
+
confirmation before continuing with the less precise website crawl. For
|
|
53
|
+
scripts and CI, pass
|
|
49
54
|
`--platform mintlify`, `--platform docusaurus`, or `--platform auto`; `--yes`
|
|
50
55
|
keeps backward-compatible auto-detection when no platform flag is supplied.
|
|
56
|
+
Explicit `--platform auto` and `--yes` runs print the live-site limitation
|
|
57
|
+
without introducing an interactive prompt.
|
|
51
58
|
|
|
52
59
|
Prefer a single binary? Install [`@thallylabs/cli`](https://www.npmjs.com/package/@thallylabs/cli)
|
|
53
60
|
and use `thally init`, which delegates here.
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
migrateDocs
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SDZZYPSN.js";
|
|
5
5
|
import {
|
|
6
6
|
logo,
|
|
7
7
|
readDocsJson,
|
|
@@ -9,15 +9,18 @@ import {
|
|
|
9
9
|
slugify,
|
|
10
10
|
success,
|
|
11
11
|
writeDocsJson
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RS6U2GSX.js";
|
|
13
13
|
|
|
14
14
|
// src/index.ts
|
|
15
15
|
import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
|
|
16
16
|
import { resolve as resolve2 } from "path";
|
|
17
17
|
|
|
18
18
|
// src/prompts.ts
|
|
19
|
-
import { input, select } from "@inquirer/prompts";
|
|
19
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
20
20
|
import { basename, resolve } from "path";
|
|
21
|
+
import {
|
|
22
|
+
parseGitHubRepositoryUrl
|
|
23
|
+
} from "@thallylabs/migrate";
|
|
21
24
|
function parseMigrationPlatform(value) {
|
|
22
25
|
if (!value || value === "auto") return void 0;
|
|
23
26
|
if (value === "mintlify" || value === "docusaurus") return value;
|
|
@@ -36,6 +39,54 @@ async function gatherMigrationPlatform(value, useDefaults) {
|
|
|
36
39
|
default: "mintlify"
|
|
37
40
|
});
|
|
38
41
|
}
|
|
42
|
+
var LIVE_URL_MIGRATION_WARNING = "Live website migration reconstructs documentation from public output and may need manual alignment. A source GitHub repository produces a more accurate migration. Use the Thally MCP afterward if the generated project needs refinement.";
|
|
43
|
+
function validateGitHubRepositorySource(value) {
|
|
44
|
+
try {
|
|
45
|
+
parseGitHubRepositoryUrl(value);
|
|
46
|
+
return true;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return error instanceof Error ? error.message : "Enter a valid public GitHub repository URL.";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function resolveAutoDetectedMigrationSource(sourceUrl, shouldPrompt) {
|
|
52
|
+
const source = new URL(sourceUrl);
|
|
53
|
+
if (source.hostname.toLowerCase() === "github.com") return sourceUrl;
|
|
54
|
+
console.warn(`
|
|
55
|
+
\u26A0 ${LIVE_URL_MIGRATION_WARNING}`);
|
|
56
|
+
if (!shouldPrompt) return sourceUrl;
|
|
57
|
+
const sourcePreference = await select({
|
|
58
|
+
message: " Which source should Thally migrate?",
|
|
59
|
+
choices: [
|
|
60
|
+
{
|
|
61
|
+
name: "Source GitHub repository (recommended)",
|
|
62
|
+
value: "github"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "Continue with the live website URL",
|
|
66
|
+
value: "website"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
default: "github"
|
|
70
|
+
});
|
|
71
|
+
if (sourcePreference === "github") {
|
|
72
|
+
const repositoryUrl = await input({
|
|
73
|
+
message: " GitHub repository URL:",
|
|
74
|
+
validate: validateGitHubRepositorySource
|
|
75
|
+
});
|
|
76
|
+
parseGitHubRepositoryUrl(repositoryUrl);
|
|
77
|
+
return repositoryUrl;
|
|
78
|
+
}
|
|
79
|
+
const hasAcceptedAlignment = await confirm({
|
|
80
|
+
message: " Continue knowing the migration may need manual alignment, using the Thally MCP afterward if needed?",
|
|
81
|
+
default: false
|
|
82
|
+
});
|
|
83
|
+
if (!hasAcceptedAlignment) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
"Migration cancelled. Re-run with the source GitHub repository for the most accurate result."
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return sourceUrl;
|
|
89
|
+
}
|
|
39
90
|
async function gatherAnswers(dirArg, useDefaults, installPreference) {
|
|
40
91
|
let projectDir;
|
|
41
92
|
if (dirArg) {
|
|
@@ -131,13 +182,26 @@ async function gatherAnswers(dirArg, useDefaults, installPreference) {
|
|
|
131
182
|
}
|
|
132
183
|
|
|
133
184
|
// src/index.ts
|
|
134
|
-
import { parseGitHubRepositoryUrl } from "@thallylabs/migrate";
|
|
185
|
+
import { parseGitHubRepositoryUrl as parseGitHubRepositoryUrl2 } from "@thallylabs/migrate";
|
|
135
186
|
|
|
136
187
|
// src/check.ts
|
|
137
188
|
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
138
189
|
import { join, extname, relative } from "path";
|
|
139
190
|
import { execFileSync } from "child_process";
|
|
191
|
+
|
|
192
|
+
// src/frontmatter.ts
|
|
140
193
|
import matter from "gray-matter";
|
|
194
|
+
var FRONTMATTER_OPTIONS = {
|
|
195
|
+
engines: {
|
|
196
|
+
javascript: () => ({}),
|
|
197
|
+
js: () => ({})
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
function parseFrontmatter(raw) {
|
|
201
|
+
return matter(raw, FRONTMATTER_OPTIONS);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/check.ts
|
|
141
205
|
import { parse as parseYaml } from "yaml";
|
|
142
206
|
function gitLocal(projectDir, args2) {
|
|
143
207
|
try {
|
|
@@ -373,7 +437,7 @@ async function runCheck(projectDir, options) {
|
|
|
373
437
|
let lineOffset = 0;
|
|
374
438
|
try {
|
|
375
439
|
const raw = readFileSync(filePath, "utf8");
|
|
376
|
-
const parsed =
|
|
440
|
+
const parsed = parseFrontmatter(raw);
|
|
377
441
|
data = parsed.data;
|
|
378
442
|
content = parsed.content;
|
|
379
443
|
lineOffset = raw.slice(0, raw.indexOf(content)).split("\n").length - 1;
|
|
@@ -474,7 +538,6 @@ thally check: ${errors.length} error(s), ${warnings.length} warning(s)`);
|
|
|
474
538
|
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
|
|
475
539
|
import { join as join2, dirname } from "path";
|
|
476
540
|
import { input as input2 } from "@inquirer/prompts";
|
|
477
|
-
import matter2 from "gray-matter";
|
|
478
541
|
import Anthropic from "@anthropic-ai/sdk";
|
|
479
542
|
import pLimit from "p-limit";
|
|
480
543
|
function readDocsJson2(projectDir) {
|
|
@@ -654,11 +717,11 @@ async function runTranslateCommand(locale, pages, force, apiKey, model, yes, pro
|
|
|
654
717
|
}
|
|
655
718
|
console.log("");
|
|
656
719
|
if (!yes) {
|
|
657
|
-
const
|
|
720
|
+
const confirm2 = await input2({
|
|
658
721
|
message: " Proceed? (Y/n):",
|
|
659
722
|
default: "Y"
|
|
660
723
|
});
|
|
661
|
-
if (
|
|
724
|
+
if (confirm2.toLowerCase() === "n") {
|
|
662
725
|
console.log("\n Aborted.");
|
|
663
726
|
return;
|
|
664
727
|
}
|
|
@@ -672,7 +735,7 @@ async function runTranslateCommand(locale, pages, force, apiKey, model, yes, pro
|
|
|
672
735
|
({ pageId, sourceFile, targetFile }) => limit(async () => {
|
|
673
736
|
try {
|
|
674
737
|
const sourceContent = readFileSync2(sourceFile, "utf8");
|
|
675
|
-
const parsed =
|
|
738
|
+
const parsed = parseFrontmatter(sourceContent);
|
|
676
739
|
if (!parsed.data.title) {
|
|
677
740
|
console.warn(` \u26A0 ${pageId}: missing title in frontmatter \u2014 translating anyway`);
|
|
678
741
|
}
|
|
@@ -732,7 +795,7 @@ function getFlagValue(flag) {
|
|
|
732
795
|
return void 0;
|
|
733
796
|
}
|
|
734
797
|
async function runMigrateCommand() {
|
|
735
|
-
|
|
798
|
+
let sourceUrl = positional[1];
|
|
736
799
|
if (!sourceUrl) {
|
|
737
800
|
console.error("\n \u274C Source URL is required.");
|
|
738
801
|
console.error(" Usage: create-thally-docs migrate <github-or-docs-url> [output-dir] [options]");
|
|
@@ -743,12 +806,22 @@ async function runMigrateCommand() {
|
|
|
743
806
|
try {
|
|
744
807
|
source = new URL(sourceUrl);
|
|
745
808
|
if (!["http:", "https:"].includes(source.protocol)) throw new Error("Only HTTP and HTTPS sources are supported.");
|
|
746
|
-
if (source.hostname.toLowerCase() === "github.com")
|
|
809
|
+
if (source.hostname.toLowerCase() === "github.com") parseGitHubRepositoryUrl2(sourceUrl);
|
|
747
810
|
} catch (err) {
|
|
748
811
|
console.error(`
|
|
749
812
|
\u274C ${err instanceof Error ? err.message : err}`);
|
|
750
813
|
process.exit(1);
|
|
751
814
|
}
|
|
815
|
+
const branch = getFlagValue("--branch");
|
|
816
|
+
const docsDir = getFlagValue("--docs-dir");
|
|
817
|
+
const yes = flags.includes("--yes") || flags.includes("-y");
|
|
818
|
+
const platformFlag = getFlagValue("--platform");
|
|
819
|
+
const platform = await gatherMigrationPlatform(platformFlag, yes);
|
|
820
|
+
if (platform === void 0) {
|
|
821
|
+
const shouldPromptForSource = platformFlag === void 0 && !yes;
|
|
822
|
+
sourceUrl = await resolveAutoDetectedMigrationSource(sourceUrl, shouldPromptForSource);
|
|
823
|
+
source = new URL(sourceUrl);
|
|
824
|
+
}
|
|
752
825
|
const apiKey = getFlagValue("--api-key") ?? process.env.ANTHROPIC_API_KEY;
|
|
753
826
|
const intoDir = getFlagValue("--into");
|
|
754
827
|
const isInto = Boolean(intoDir);
|
|
@@ -758,13 +831,9 @@ async function runMigrateCommand() {
|
|
|
758
831
|
} else if (positional[2]) {
|
|
759
832
|
projectDir = resolve2(positional[2]);
|
|
760
833
|
} else {
|
|
761
|
-
const sourceName = source.hostname.toLowerCase() === "github.com" ?
|
|
834
|
+
const sourceName = source.hostname.toLowerCase() === "github.com" ? parseGitHubRepositoryUrl2(sourceUrl).repo : source.pathname.split("/").filter(Boolean).at(-1) ?? source.hostname.split(".")[0];
|
|
762
835
|
projectDir = resolve2(`${slugify(sourceName)}-docs`);
|
|
763
836
|
}
|
|
764
|
-
const branch = getFlagValue("--branch");
|
|
765
|
-
const docsDir = getFlagValue("--docs-dir");
|
|
766
|
-
const yes = flags.includes("--yes") || flags.includes("-y");
|
|
767
|
-
const platform = await gatherMigrationPlatform(getFlagValue("--platform"), yes);
|
|
768
837
|
const maxPagesValue = getFlagValue("--max-pages");
|
|
769
838
|
const maxPages = maxPagesValue ? Number(maxPagesValue) : void 0;
|
|
770
839
|
if (maxPages !== void 0 && (!Number.isInteger(maxPages) || maxPages < 1 || maxPages > 1e3)) {
|
package/dist/migrate/index.js
CHANGED
package/dist/scaffold.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-thally-docs",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "Scaffold a
|
|
3
|
+
"version": "0.8.1",
|
|
4
|
+
"description": "Scaffold the first documentation surface in a Thally product-knowledge pipeline.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=18"
|