@telepat/ideon 0.1.27 → 0.1.28

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.
Files changed (2) hide show
  1. package/dist/ideon.js +64 -86
  2. package/package.json +1 -1
package/dist/ideon.js CHANGED
@@ -1424,7 +1424,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
1424
1424
  // package.json
1425
1425
  var package_default = {
1426
1426
  name: "@telepat/ideon",
1427
- version: "0.1.27",
1427
+ version: "0.1.28",
1428
1428
  description: "CLI for generating rich articles and images from ideas.",
1429
1429
  type: "module",
1430
1430
  repository: {
@@ -6152,10 +6152,44 @@ function resolveCustomLinks(existing, addRaw, removeExpressions) {
6152
6152
  }
6153
6153
 
6154
6154
  // src/cli/commands/export.ts
6155
- import { copyFile as copyFile2, mkdir as mkdir7, readFile as readFile9, stat as stat5, writeFile as writeFile6 } from "fs/promises";
6155
+ import { copyFile as copyFile2, mkdir as mkdir7, readFile as readFile10, stat as stat5, writeFile as writeFile6 } from "fs/promises";
6156
6156
  import path12 from "path";
6157
6157
 
6158
6158
  // src/output/enrichMarkdownWithLinks.ts
6159
+ import { readFile as readFile8 } from "fs/promises";
6160
+ async function loadLinksFromSidecar(markdownPath) {
6161
+ const linksPath = resolveLinksPath(markdownPath);
6162
+ let raw;
6163
+ try {
6164
+ raw = await readFile8(linksPath, "utf8");
6165
+ } catch {
6166
+ return [];
6167
+ }
6168
+ let parsed;
6169
+ try {
6170
+ parsed = JSON.parse(raw);
6171
+ } catch {
6172
+ return [];
6173
+ }
6174
+ if (typeof parsed !== "object" || parsed === null) {
6175
+ return [];
6176
+ }
6177
+ const record = parsed;
6178
+ const links = Array.isArray(record.links) ? record.links : [];
6179
+ const customLinks = Array.isArray(record.customLinks) ? record.customLinks : [];
6180
+ const combined = [...customLinks, ...links];
6181
+ return combined.filter((entry) => {
6182
+ if (typeof entry !== "object" || entry === null) {
6183
+ return false;
6184
+ }
6185
+ const e = entry;
6186
+ return typeof e.expression === "string" && typeof e.url === "string" && (e.title === null || typeof e.title === "string");
6187
+ }).map((entry) => ({
6188
+ expression: entry.expression.trim(),
6189
+ url: entry.url.trim(),
6190
+ title: entry.title
6191
+ })).filter((entry) => entry.expression.length > 0 && entry.url.length > 0);
6192
+ }
6159
6193
  function enrichMarkdownWithLinks(markdown, links) {
6160
6194
  if (links.length === 0) {
6161
6195
  return markdown;
@@ -6202,14 +6236,29 @@ function isInProtectedSpan(content, start, end) {
6202
6236
  return true;
6203
6237
  }
6204
6238
  }
6239
+ if (/^#{1,6}\s/.test(line)) {
6240
+ return true;
6241
+ }
6205
6242
  return false;
6206
6243
  }
6207
6244
  function escapeRegExp(value2) {
6208
- return value2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6245
+ return value2.replace(/[.*+?^{}()|[\]\\]/g, "\\$&");
6246
+ }
6247
+ function enrichWithFrontmatterGuard(markdown, links) {
6248
+ if (links.length === 0) {
6249
+ return markdown;
6250
+ }
6251
+ const frontmatterMatch = markdown.match(/^---\s*\n[\s\S]*?\n---\s*\n?/);
6252
+ if (!frontmatterMatch) {
6253
+ return enrichMarkdownWithLinks(markdown, links);
6254
+ }
6255
+ const frontmatter = frontmatterMatch[0];
6256
+ const body = markdown.slice(frontmatter.length);
6257
+ return `${frontmatter}${enrichMarkdownWithLinks(body, links)}`;
6209
6258
  }
6210
6259
 
6211
6260
  // src/server/previewHelpers.ts
6212
- import { readdir, stat as stat4, readFile as readFile8 } from "fs/promises";
6261
+ import { readdir, stat as stat4, readFile as readFile9 } from "fs/promises";
6213
6262
  import path11 from "path";
6214
6263
  var DEFAULT_PORT = 4173;
6215
6264
  var CONTENT_TYPE_ORDER = ["article", "blog-post", "x-thread", "x-post", "linkedin-post", "reddit-post", "newsletter"];
@@ -6311,7 +6360,7 @@ function extractCoverImageUrl(markdown) {
6311
6360
  return match?.[1] ?? null;
6312
6361
  }
6313
6362
  async function extractArticleMetadata(markdownPath) {
6314
- const markdown = await readFile8(markdownPath, "utf8");
6363
+ const markdown = await readFile9(markdownPath, "utf8");
6315
6364
  const fileStat = await stat4(markdownPath);
6316
6365
  const slug = extractFrontmatterSlug(markdown) ?? path11.basename(markdownPath, ".md");
6317
6366
  const title = extractHeadingTitle(stripFrontmatter2(markdown)) ?? slug;
@@ -6468,7 +6517,7 @@ async function resolvePrimaryContentType(outputs) {
6468
6517
  }
6469
6518
  const jobPath = path11.join(generationDir, "job.json");
6470
6519
  try {
6471
- const raw = await readFile8(jobPath, "utf8");
6520
+ const raw = await readFile9(jobPath, "utf8");
6472
6521
  const parsed = JSON.parse(raw);
6473
6522
  const targets = Array.isArray(parsed.contentTargets) ? parsed.contentTargets : Array.isArray(parsed.settings?.contentTargets) ? parsed.settings.contentTargets : [];
6474
6523
  const primary = targets.find((target) => target?.role === "primary" && typeof target.contentType === "string");
@@ -6509,7 +6558,7 @@ async function runOutputCommand(options, dependencies = {}) {
6509
6558
  );
6510
6559
  }
6511
6560
  const sourceMarkdownPath = articleOutput.sourcePath;
6512
- const sourceMarkdown = await readFile9(sourceMarkdownPath, "utf8");
6561
+ const sourceMarkdown = await readFile10(sourceMarkdownPath, "utf8");
6513
6562
  const slug = extractFrontmatterSlug2(sourceMarkdown) ?? path12.basename(sourceMarkdownPath, ".md");
6514
6563
  const exportFilename = `${slug}.md`;
6515
6564
  const destinationDir = await resolveDestinationDir(options.destinationPath, cwd2);
@@ -6520,7 +6569,7 @@ async function runOutputCommand(options, dependencies = {}) {
6520
6569
  );
6521
6570
  }
6522
6571
  await mkdir7(destinationDir, { recursive: true });
6523
- const links = await loadLinks(sourceMarkdownPath);
6572
+ const links = await loadLinksFromSidecar(sourceMarkdownPath);
6524
6573
  const enrichedMarkdown = enrichWithFrontmatterGuard(sourceMarkdown, links);
6525
6574
  const sourceDir = path12.dirname(sourceMarkdownPath);
6526
6575
  const allFiles = await listFilesRecursively(sourceDir, () => true);
@@ -6572,51 +6621,6 @@ async function fileExists2(filePath) {
6572
6621
  return false;
6573
6622
  }
6574
6623
  }
6575
- async function loadLinks(markdownPath) {
6576
- const linksPath = resolveLinksPath(markdownPath);
6577
- let raw;
6578
- try {
6579
- raw = await readFile9(linksPath, "utf8");
6580
- } catch {
6581
- return [];
6582
- }
6583
- let parsed;
6584
- try {
6585
- parsed = JSON.parse(raw);
6586
- } catch {
6587
- return [];
6588
- }
6589
- if (typeof parsed !== "object" || parsed === null) {
6590
- return [];
6591
- }
6592
- const record = parsed;
6593
- const links = Array.isArray(record.links) ? record.links : [];
6594
- const customLinks = Array.isArray(record.customLinks) ? record.customLinks : [];
6595
- const combined = [...customLinks, ...links];
6596
- return combined.filter((entry) => {
6597
- if (typeof entry !== "object" || entry === null) {
6598
- return false;
6599
- }
6600
- const e = entry;
6601
- return typeof e.expression === "string" && typeof e.url === "string" && (e.title === null || typeof e.title === "string");
6602
- }).map((entry) => ({
6603
- expression: entry.expression.trim(),
6604
- url: entry.url.trim(),
6605
- title: entry.title
6606
- })).filter((entry) => entry.expression.length > 0 && entry.url.length > 0);
6607
- }
6608
- function enrichWithFrontmatterGuard(markdown, links) {
6609
- if (links.length === 0) {
6610
- return markdown;
6611
- }
6612
- const frontmatterMatch = markdown.match(/^---\s*\n[\s\S]*?\n---\s*\n?/);
6613
- if (!frontmatterMatch) {
6614
- return enrichMarkdownWithLinks(markdown, links);
6615
- }
6616
- const frontmatter = frontmatterMatch[0];
6617
- const body = markdown.slice(frontmatter.length);
6618
- return `${frontmatter}${enrichMarkdownWithLinks(body, links)}`;
6619
- }
6620
6624
  function extractFrontmatterSlug2(markdown) {
6621
6625
  const frontmatterMatch = markdown.match(/^---\s*\n([\s\S]*?)\n---\s*\n?/);
6622
6626
  const block = frontmatterMatch?.[1];
@@ -7498,7 +7502,7 @@ import { spawn } from "child_process";
7498
7502
  // src/server/previewServer.ts
7499
7503
  import { execFile } from "child_process";
7500
7504
  import { promisify } from "util";
7501
- import { readFile as readFile10, stat as stat6 } from "fs/promises";
7505
+ import { readFile as readFile11, stat as stat6 } from "fs/promises";
7502
7506
  import { watch as fsWatch } from "fs";
7503
7507
  import path13 from "path";
7504
7508
  import { fileURLToPath } from "url";
@@ -7598,7 +7602,7 @@ async function startPreviewServer(options) {
7598
7602
  if (options.watch) {
7599
7603
  let html2;
7600
7604
  try {
7601
- html2 = await readFile10(path13.join(previewClientDir, "index.html"), "utf8");
7605
+ html2 = await readFile11(path13.join(previewClientDir, "index.html"), "utf8");
7602
7606
  } catch {
7603
7607
  res.status(200).type("html").send(
7604
7608
  `<!doctype html><html><head><meta charset="utf-8"><title>Rebuilding\u2026</title><style>body{margin:0;display:flex;align-items:center;justify-content:center;height:100vh;font-family:sans-serif;background:#101820;color:#e0eaf0}p{font-size:15px;opacity:.7}</style></head><body><p>Rebuilding\u2026</p><script>const s=new EventSource('/api/__reload');s.onmessage=function(){location.reload()};</script></body></html>`
@@ -7662,7 +7666,7 @@ async function getArticleContent(generationId, markdownOutputDir) {
7662
7666
  generation.outputs.map(async (output) => {
7663
7667
  let markdown = "";
7664
7668
  try {
7665
- markdown = await readFile10(output.sourcePath, "utf8");
7669
+ markdown = await readFile11(output.sourcePath, "utf8");
7666
7670
  } catch (error) {
7667
7671
  if (isMissingFileError(error)) {
7668
7672
  throw new MissingArticleError(`Generation "${generationId}" no longer exists.`);
@@ -7718,41 +7722,15 @@ function isMissingFileError(error) {
7718
7722
  }
7719
7723
  async function renderArticleHtml(markdown, generationId, sourcePath) {
7720
7724
  let content = stripFrontmatter2(markdown);
7721
- const links = await loadSavedLinks(sourcePath);
7725
+ const links = await loadLinksFromSidecar(sourcePath);
7722
7726
  content = enrichMarkdownWithLinks(content, links);
7723
7727
  const html = await marked.parse(content);
7724
7728
  return rewriteRelativeAssetUrls(html, generationId);
7725
7729
  }
7726
- async function loadSavedLinks(markdownPath) {
7727
- const linksPath = resolveLinksPath(markdownPath);
7728
- try {
7729
- const raw = await readFile10(linksPath, "utf8");
7730
- const parsed = JSON.parse(raw);
7731
- if (!Array.isArray(parsed.links)) {
7732
- return [];
7733
- }
7734
- return parsed.links.filter((entry) => {
7735
- if (typeof entry !== "object" || entry === null) {
7736
- return false;
7737
- }
7738
- const record = entry;
7739
- return typeof record.expression === "string" && typeof record.url === "string" && (record.title === null || typeof record.title === "string");
7740
- }).map((entry) => ({
7741
- expression: entry.expression.trim(),
7742
- url: entry.url.trim(),
7743
- title: entry.title
7744
- })).filter((entry) => entry.expression.length > 0 && entry.url.length > 0);
7745
- } catch (error) {
7746
- if (isMissingFileError(error)) {
7747
- return [];
7748
- }
7749
- return [];
7750
- }
7751
- }
7752
7730
  async function loadSavedInteractions(generationDir) {
7753
7731
  const interactionsPath = path13.join(generationDir, "model.interactions.json");
7754
7732
  try {
7755
- const raw = await readFile10(interactionsPath, "utf8");
7733
+ const raw = await readFile11(interactionsPath, "utf8");
7756
7734
  const parsed = JSON.parse(raw);
7757
7735
  const llmCalls = Array.isArray(parsed.llmCalls) ? parsed.llmCalls.filter(isPreviewLlmInteraction) : [];
7758
7736
  const t2iCalls = Array.isArray(parsed.t2iCalls) ? parsed.t2iCalls.filter(isPreviewT2IInteraction) : [];
@@ -7770,7 +7748,7 @@ async function loadSavedInteractions(generationDir) {
7770
7748
  async function loadSavedAnalyticsSummary(generationDir) {
7771
7749
  const analyticsPath = path13.join(generationDir, "generation.analytics.json");
7772
7750
  try {
7773
- const raw = await readFile10(analyticsPath, "utf8");
7751
+ const raw = await readFile11(analyticsPath, "utf8");
7774
7752
  const parsed = JSON.parse(raw);
7775
7753
  const summary = parsed.summary;
7776
7754
  if (!summary || typeof summary !== "object") {
@@ -7794,7 +7772,7 @@ async function loadSavedAnalyticsSummary(generationDir) {
7794
7772
  async function loadSavedMetaJson(generationDir) {
7795
7773
  const metaJsonPath = path13.join(generationDir, "meta.json");
7796
7774
  try {
7797
- const raw = await readFile10(metaJsonPath, "utf8");
7775
+ const raw = await readFile11(metaJsonPath, "utf8");
7798
7776
  return JSON.parse(raw);
7799
7777
  } catch {
7800
7778
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telepat/ideon",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "description": "CLI for generating rich articles and images from ideas.",
5
5
  "type": "module",
6
6
  "repository": {