next-md-negotiate 1.1.0 → 1.1.2

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
@@ -28,7 +28,7 @@ No new URLs. No duplicate routing. The client just sets an `Accept` header.
28
28
  npm install next-md-negotiate
29
29
  ```
30
30
 
31
- > Or run `npx next-md-negotiate init` to scaffold the files below automatically.
31
+ > To scaffold everything automatically, run `npx next-md-negotiate init`.
32
32
 
33
33
  ## Quick start
34
34
 
@@ -293,13 +293,13 @@ React component that renders a `<script type="text/llms.txt">` tag to help LLM a
293
293
 
294
294
  | Prop | Type | Default | Description |
295
295
  |---|---|---|---|
296
- | `message` | `string` | `'This page is available as clean Markdown...'` | The hint text inside the script tag |
296
+ | `message` | `string` | `'You are viewing the HTML version of this page...'` | The hint text inside the script tag |
297
297
 
298
298
  ### CLI commands
299
299
 
300
300
  | Command | Description |
301
301
  |---|---|
302
- | `next-md-negotiate init` | Scaffold route handler, config file, and rewrites |
302
+ | `next-md-negotiate init` | Scaffold route handler, config file, and rewrites. Offers to add LLM hints when routes are already defined. Pass `--add-hints` to skip the prompt. |
303
303
  | `next-md-negotiate add-hints` | Inject `LlmHint` into page files for all configured routes |
304
304
  | `next-md-negotiate remove-hints` | Remove `LlmHint` from page files for all configured routes |
305
305
 
package/dist/cli.js CHANGED
@@ -491,6 +491,23 @@ var x = class {
491
491
  }
492
492
  }
493
493
  };
494
+ var kt = class extends x {
495
+ get cursor() {
496
+ return this.value ? 0 : 1;
497
+ }
498
+ get _value() {
499
+ return this.cursor === 0;
500
+ }
501
+ constructor(e2) {
502
+ super(e2, false), this.value = !!e2.initialValue, this.on("userInput", () => {
503
+ this.value = this._value;
504
+ }), this.on("confirm", (s) => {
505
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = s, this.state = "submit", this.close();
506
+ }), this.on("cursor", () => {
507
+ this.value = !this.value;
508
+ });
509
+ }
510
+ };
494
511
  var Wt = class extends x {
495
512
  constructor(e2) {
496
513
  super(e2, false);
@@ -781,6 +798,33 @@ var X2 = (t) => {
781
798
  for (const A of f) for (const w of A) B2.push(w);
782
799
  return h && B2.push(g), B2;
783
800
  };
801
+ var Re = (t) => {
802
+ const r = t.active ?? "Yes", s = t.inactive ?? "No";
803
+ return new kt({ active: r, inactive: s, signal: t.signal, input: t.input, output: t.output, initialValue: t.initialValue ?? true, render() {
804
+ const i = t.withGuide ?? _.withGuide, a = `${i ? `${import_picocolors.default.gray(d)}
805
+ ` : ""}${W2(this.state)} ${t.message}
806
+ `, o = this.value ? r : s;
807
+ switch (this.state) {
808
+ case "submit": {
809
+ const u = i ? `${import_picocolors.default.gray(d)} ` : "";
810
+ return `${a}${u}${import_picocolors.default.dim(o)}`;
811
+ }
812
+ case "cancel": {
813
+ const u = i ? `${import_picocolors.default.gray(d)} ` : "";
814
+ return `${a}${u}${import_picocolors.default.strikethrough(import_picocolors.default.dim(o))}${i ? `
815
+ ${import_picocolors.default.gray(d)}` : ""}`;
816
+ }
817
+ default: {
818
+ const u = i ? `${import_picocolors.default.cyan(d)} ` : "", l = i ? import_picocolors.default.cyan(x2) : "";
819
+ return `${a}${u}${this.value ? `${import_picocolors.default.green(Q2)} ${r}` : `${import_picocolors.default.dim(H2)} ${import_picocolors.default.dim(r)}`}${t.vertical ? i ? `
820
+ ${import_picocolors.default.cyan(d)} ` : `
821
+ ` : ` ${import_picocolors.default.dim("/")} `}${this.value ? `${import_picocolors.default.dim(H2)} ${import_picocolors.default.dim(s)}` : `${import_picocolors.default.green(Q2)} ${s}`}
822
+ ${l}
823
+ `;
824
+ }
825
+ }
826
+ } }).prompt();
827
+ };
784
828
  var R2 = { message: (t = [], { symbol: r = import_picocolors.default.gray(d), secondarySymbol: s = import_picocolors.default.gray(d), output: i = process.stdout, spacing: a = 1, withGuide: o } = {}) => {
785
829
  const u = [], l = o ?? _.withGuide, n = l ? s : "", c = l ? `${r} ` : "", g = l ? `${s} ` : "";
786
830
  for (let p = 0; p < a; p++) u.push(n);
@@ -1223,6 +1267,35 @@ export const mdConfig = [
1223
1267
  // }),
1224
1268
  ];
1225
1269
  `;
1270
+ function applyHints(cwd, project, mdConfigPath) {
1271
+ const configContent = readFileSync2(mdConfigPath, "utf-8");
1272
+ const defaultHintText = extractDefaultHintText(configContent);
1273
+ const entries = extractConfigEntries(configContent);
1274
+ if (entries.length === 0) {
1275
+ logWarn("No createMdVersion() entries found in config.");
1276
+ return;
1277
+ }
1278
+ for (const entry of entries) {
1279
+ if (entry.skipHint) {
1280
+ logWarn(`Skipped ${entry.pattern} (skipHint: true)`);
1281
+ continue;
1282
+ }
1283
+ const pageFile = resolvePageFile(cwd, entry.pattern, project.useSrc, project.hasAppDir);
1284
+ if (!pageFile) {
1285
+ logWarn(`Could not find page file for pattern: ${entry.pattern}`);
1286
+ continue;
1287
+ }
1288
+ const content = readFileSync2(pageFile, "utf-8");
1289
+ const hintText = entry.hintText ?? defaultHintText;
1290
+ const updated = injectLlmHint(content, hintText);
1291
+ if (updated === null) {
1292
+ logWarn(`Skipped ${pageFile.replace(cwd + "/", "")} (already has LlmHint)`);
1293
+ continue;
1294
+ }
1295
+ writeFileSync2(pageFile, updated);
1296
+ logSuccess(`Injected LlmHint into ${pageFile.replace(cwd + "/", "")}`);
1297
+ }
1298
+ }
1226
1299
  async function runInit(args) {
1227
1300
  const flags = new Set(args);
1228
1301
  const cwd = process.cwd();
@@ -1248,6 +1321,7 @@ async function runInit(args) {
1248
1321
  );
1249
1322
  process.exit(1);
1250
1323
  }
1324
+ let configExisted = false;
1251
1325
  try {
1252
1326
  if (project.hasAppDir) {
1253
1327
  const appDir = join4(cwd, project.useSrc ? "src" : "", "app");
@@ -1275,6 +1349,7 @@ async function runInit(args) {
1275
1349
  const configPath = join4(project.configDir, "md.config.ts");
1276
1350
  if (existsSync3(configPath)) {
1277
1351
  logWarn("Skipped md.config.ts (already exists)");
1352
+ configExisted = true;
1278
1353
  } else {
1279
1354
  writeFileSync2(configPath, MD_CONFIG);
1280
1355
  logSuccess("Created md.config.ts");
@@ -1316,7 +1391,28 @@ async function runInit(args) {
1316
1391
  } else {
1317
1392
  printGenericInstructions();
1318
1393
  }
1319
- logInfo("Define your routes in md.config.ts");
1394
+ if (flags.has("--add-hints")) {
1395
+ const mdConfigPath = findMdConfig(cwd, project.configDir);
1396
+ if (mdConfigPath) applyHints(cwd, project, mdConfigPath);
1397
+ } else if (isTTY && configExisted) {
1398
+ const mdConfigPath = findMdConfig(cwd, project.configDir);
1399
+ if (mdConfigPath) {
1400
+ const configContent = readFileSync2(mdConfigPath, "utf-8");
1401
+ const entries = extractConfigEntries(configContent);
1402
+ if (entries.length > 0) {
1403
+ const shouldAddHints = await Re({
1404
+ message: "Add LlmHint to your pages for LLM discoverability?",
1405
+ initialValue: false
1406
+ });
1407
+ if (!Ct(shouldAddHints) && shouldAddHints) {
1408
+ applyHints(cwd, project, mdConfigPath);
1409
+ }
1410
+ }
1411
+ }
1412
+ }
1413
+ if (!configExisted) {
1414
+ logInfo("Define your routes in md.config.ts, then run 'npx next-md-negotiate add-hints' for LLM discoverability.");
1415
+ }
1320
1416
  if (isTTY) Le("You're all set!");
1321
1417
  }
1322
1418
  async function runAddHints() {
@@ -1333,33 +1429,7 @@ async function runAddHints() {
1333
1429
  logError("Error: Could not find md.config.ts or md.config.js. Run 'next-md-negotiate init' first.");
1334
1430
  process.exit(1);
1335
1431
  }
1336
- const configContent = readFileSync2(mdConfigPath, "utf-8");
1337
- const defaultHintText = extractDefaultHintText(configContent);
1338
- const entries = extractConfigEntries(configContent);
1339
- if (entries.length === 0) {
1340
- logWarn("No createMdVersion() entries found in config.");
1341
- return;
1342
- }
1343
- for (const entry of entries) {
1344
- if (entry.skipHint) {
1345
- logWarn(`Skipped ${entry.pattern} (skipHint: true)`);
1346
- continue;
1347
- }
1348
- const pageFile = resolvePageFile(cwd, entry.pattern, project.useSrc, project.hasAppDir);
1349
- if (!pageFile) {
1350
- logWarn(`Could not find page file for pattern: ${entry.pattern}`);
1351
- continue;
1352
- }
1353
- const content = readFileSync2(pageFile, "utf-8");
1354
- const hintText = entry.hintText ?? defaultHintText;
1355
- const updated = injectLlmHint(content, hintText);
1356
- if (updated === null) {
1357
- logWarn(`Skipped ${pageFile.replace(cwd + "/", "")} (already has LlmHint)`);
1358
- continue;
1359
- }
1360
- writeFileSync2(pageFile, updated);
1361
- logSuccess(`Injected LlmHint into ${pageFile.replace(cwd + "/", "")}`);
1362
- }
1432
+ applyHints(cwd, project, mdConfigPath);
1363
1433
  }
1364
1434
  async function runRemoveHints() {
1365
1435
  const cwd = process.cwd();
package/dist/index.cjs CHANGED
@@ -213,7 +213,7 @@ function createNegotiatorFromConfig(handlers, options) {
213
213
 
214
214
  // src/LlmHint.ts
215
215
  var import_react = require("react");
216
- var DEFAULT_MESSAGE = "This page is available as clean Markdown.\nRe-request this URL with the header: Accept: text/markdown";
216
+ var DEFAULT_MESSAGE = "You are viewing the HTML version of this page. A structured markdown version is available and is significantly smaller and easier to parse. To receive the markdown version, re-request this exact URL with the HTTP header `Accept: text/markdown`. Other pages on this site may also support this content negotiation.";
217
217
  function LlmHint(props) {
218
218
  return (0, import_react.createElement)("script", {
219
219
  type: "text/llms.txt",
package/dist/index.js CHANGED
@@ -180,7 +180,7 @@ function createNegotiatorFromConfig(handlers, options) {
180
180
 
181
181
  // src/LlmHint.ts
182
182
  import { createElement } from "react";
183
- var DEFAULT_MESSAGE = "This page is available as clean Markdown.\nRe-request this URL with the header: Accept: text/markdown";
183
+ var DEFAULT_MESSAGE = "You are viewing the HTML version of this page. A structured markdown version is available and is significantly smaller and easier to parse. To receive the markdown version, re-request this exact URL with the HTTP header `Accept: text/markdown`. Other pages on this site may also support this content negotiation.";
184
184
  function LlmHint(props) {
185
185
  return createElement("script", {
186
186
  type: "text/llms.txt",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-md-negotiate",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Content negotiation for Next.js - serve Markdown to LLMs, HTML to browsers, from a single URL",
5
5
  "type": "module",
6
6
  "exports": {