@json-to-office/jto 2.4.0 → 3.0.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.
Files changed (57) hide show
  1. package/dist/cli.js +123 -39
  2. package/dist/cli.js.map +1 -1
  3. package/dist/client/assets/HomePage-BlzZ7qG4.js +245 -0
  4. package/dist/client/assets/HomePage-BlzZ7qG4.js.map +1 -0
  5. package/dist/client/assets/{JsonEditorPage-DjLAUBv5.js → JsonEditorPage-kWuP_kL3.js} +3 -3
  6. package/dist/client/assets/{JsonEditorPage-DjLAUBv5.js.map → JsonEditorPage-kWuP_kL3.js.map} +1 -1
  7. package/dist/client/assets/{MonacoPluginProvider-D_GUFwWQ.js → MonacoPluginProvider-Dbv1PrO2.js} +6 -6
  8. package/dist/client/assets/{MonacoPluginProvider-D_GUFwWQ.js.map → MonacoPluginProvider-Dbv1PrO2.js.map} +1 -1
  9. package/dist/client/assets/{_virtual_jto-plugin-type-libs-9elxvZT2.js → _virtual_jto-plugin-type-libs-B6KyD9RL.js} +9182 -4529
  10. package/dist/client/assets/{_virtual_jto-plugin-type-libs-9elxvZT2.js.map → _virtual_jto-plugin-type-libs-B6KyD9RL.js.map} +1 -1
  11. package/dist/client/assets/_virtual_jto-sandbox-runtime-Bzo2M5U7.js +2 -0
  12. package/dist/client/assets/_virtual_jto-sandbox-runtime-Bzo2M5U7.js.map +1 -0
  13. package/dist/client/assets/editor-CwEocOY2.js +16 -0
  14. package/dist/client/assets/editor-CwEocOY2.js.map +1 -0
  15. package/dist/client/assets/editor-monaco-json-D_oiidNg.js +24 -0
  16. package/dist/client/assets/editor-monaco-json-D_oiidNg.js.map +1 -0
  17. package/dist/client/assets/index--kF4jVbp.css +1 -0
  18. package/dist/client/assets/index-DFJaEoi0.js +27 -0
  19. package/dist/client/assets/index-DFJaEoi0.js.map +1 -0
  20. package/dist/client/assets/index-UheDso2P.js +2 -0
  21. package/dist/client/assets/index-UheDso2P.js.map +1 -0
  22. package/dist/client/assets/preview-CWdUATNl.js +4 -0
  23. package/dist/client/assets/preview-CWdUATNl.js.map +1 -0
  24. package/dist/client/assets/useQualityAnalysis-Cl4QPeOT.js +6 -0
  25. package/dist/client/assets/useQualityAnalysis-Cl4QPeOT.js.map +1 -0
  26. package/dist/client/index.html +2 -2
  27. package/dist/client/templates/client-report-blocks.docx.json +791 -0
  28. package/dist/client/templates/consulting-deck-blocks.pptx.json +455 -0
  29. package/dist/client/templates/data-report-presentation.pptx.json +108 -36
  30. package/dist/client/templates/management-plan.pptx.json +100 -22
  31. package/dist/client/templates/minimalist-pitch-deck.pptx.json +172 -101
  32. package/dist/prompts/instructions-edit-document-pptx-blocks.md +77 -0
  33. package/dist/prompts/instructions-edit-document-pptx-slides.md +15 -21
  34. package/dist/prompts/instructions-edit-document-pptx.md +34 -53
  35. package/dist/prompts/instructions-edit-pptx.md +9 -8
  36. package/dist/prompts/instructions-generate-pptx.md +13 -17
  37. package/dist/prompts/pptx-core.md +104 -127
  38. package/dist/prompts/pptx-design.md +115 -109
  39. package/package.json +10 -9
  40. package/dist/client/assets/HomePage-mtUb6jxc.js +0 -251
  41. package/dist/client/assets/HomePage-mtUb6jxc.js.map +0 -1
  42. package/dist/client/assets/_virtual_jto-sandbox-runtime-Dqq17bow.js +0 -2
  43. package/dist/client/assets/_virtual_jto-sandbox-runtime-Dqq17bow.js.map +0 -1
  44. package/dist/client/assets/editor-ZbEHVEFs.js +0 -16
  45. package/dist/client/assets/editor-ZbEHVEFs.js.map +0 -1
  46. package/dist/client/assets/editor-monaco-json-FaaVfftD.js +0 -24
  47. package/dist/client/assets/editor-monaco-json-FaaVfftD.js.map +0 -1
  48. package/dist/client/assets/editor-refs-store-DAEAPqEk.js +0 -2
  49. package/dist/client/assets/editor-refs-store-DAEAPqEk.js.map +0 -1
  50. package/dist/client/assets/index-Bj6ZAKUc.css +0 -1
  51. package/dist/client/assets/index-DRbATnbJ.js +0 -5
  52. package/dist/client/assets/index-DRbATnbJ.js.map +0 -1
  53. package/dist/client/assets/preview-CM2ywF-8.js +0 -4
  54. package/dist/client/assets/preview-CM2ywF-8.js.map +0 -1
  55. package/dist/client/assets/useQualityAnalysis-ClgkaIc2.js +0 -6
  56. package/dist/client/assets/useQualityAnalysis-ClgkaIc2.js.map +0 -1
  57. package/dist/prompts/instructions-edit-document-pptx-templates.md +0 -63
package/dist/cli.js CHANGED
@@ -2914,14 +2914,79 @@ var init_browser_plugin_schema = __esm({
2914
2914
  }
2915
2915
  });
2916
2916
 
2917
+ // src/server/services/block-references.ts
2918
+ import { readFile } from "fs/promises";
2919
+ import { PluginDiscoveryService as PluginDiscoveryService2 } from "@json-to-office/jto-cli";
2920
+ import {
2921
+ blockReferencesFromDocument,
2922
+ blockSlotFacts
2923
+ } from "@json-to-office/shared";
2924
+ async function discoverBlockReferences(format) {
2925
+ const cached = cache.get(format);
2926
+ if (cached && Date.now() - cached.at < TTL_MS) return cached.references;
2927
+ const discovery = new PluginDiscoveryService2({
2928
+ maxDepth: 10,
2929
+ includeNodeModules: false,
2930
+ verbose: false
2931
+ });
2932
+ const documents = await discovery.discoverDocuments(format);
2933
+ const references = [];
2934
+ for (const document of documents) {
2935
+ try {
2936
+ references.push(
2937
+ ...blockReferencesFromDocument(
2938
+ JSON.parse(await readFile(document.path, "utf-8")),
2939
+ { template: document.name, format }
2940
+ )
2941
+ );
2942
+ } catch {
2943
+ }
2944
+ }
2945
+ cache.set(format, { at: Date.now(), references });
2946
+ return references;
2947
+ }
2948
+ function blockReferencesPrompt(references) {
2949
+ if (!references.length)
2950
+ return "_No reference blocks are available on this server; define the blocks the deck needs yourself._";
2951
+ return references.map((reference) => {
2952
+ const slots = Object.entries(reference.definition.slots).map(
2953
+ ([name, slot]) => `- \`${name}\` \u2014 ${[slot.type, ...blockSlotFacts(slot)].join(", ")}${slot.description ? `: ${slot.description}` : ""}`
2954
+ );
2955
+ const dependencies = reference.dependencies.length ? `
2956
+ Also copy: ${reference.dependencies.map((name) => `\`${name}\``).join(", ")} (invoked by this definition).` : "";
2957
+ return [
2958
+ `### \`${reference.name}\` (from ${reference.template})`,
2959
+ reference.description,
2960
+ slots.length ? slots.join("\n") : "_No slots._",
2961
+ `Definition to copy into \`props.blocks\`:${dependencies}`,
2962
+ "```json",
2963
+ JSON.stringify({ [reference.name]: reference.definition }, null, 2),
2964
+ "```",
2965
+ "Invocation:",
2966
+ "```json",
2967
+ JSON.stringify(reference.example, null, 2),
2968
+ "```"
2969
+ ].filter(Boolean).join("\n\n");
2970
+ }).join("\n\n");
2971
+ }
2972
+ var TTL_MS, cache;
2973
+ var init_block_references = __esm({
2974
+ "src/server/services/block-references.ts"() {
2975
+ "use strict";
2976
+ init_esm_shims();
2977
+ TTL_MS = 1e4;
2978
+ cache = /* @__PURE__ */ new Map();
2979
+ }
2980
+ });
2981
+
2917
2982
  // src/server/routes/discovery.ts
2918
2983
  import { Hono as Hono3 } from "hono";
2919
2984
  import { HTTPException as HTTPException5 } from "hono/http-exception";
2920
2985
  import { bodyLimit as bodyLimit3 } from "hono/body-limit";
2921
2986
  import { Type as Type3 } from "@sinclair/typebox";
2922
- import { readFile, stat } from "fs/promises";
2987
+ import { readFile as readFile2, stat } from "fs/promises";
2923
2988
  import {
2924
- PluginDiscoveryService as PluginDiscoveryService2,
2989
+ PluginDiscoveryService as PluginDiscoveryService3,
2925
2990
  PluginRegistry as PluginRegistry3
2926
2991
  } from "@json-to-office/jto-cli";
2927
2992
  import { latestVersion } from "@json-to-office/shared";
@@ -3085,6 +3150,7 @@ var init_discovery = __esm({
3085
3150
  init_auth();
3086
3151
  init_config();
3087
3152
  init_browser_plugin_schema();
3153
+ init_block_references();
3088
3154
  discoveryRouter = new Hono3();
3089
3155
  BrowserPluginVersionSchema = Type3.Object(
3090
3156
  {
@@ -3124,7 +3190,7 @@ var init_discovery = __esm({
3124
3190
  discoveryRouter.get("/all", async (c) => {
3125
3191
  try {
3126
3192
  const format = Container.getAdapter().name;
3127
- const discovery = new PluginDiscoveryService2({
3193
+ const discovery = new PluginDiscoveryService3({
3128
3194
  maxDepth: 10,
3129
3195
  includeNodeModules: false,
3130
3196
  verbose: false
@@ -3159,7 +3225,7 @@ var init_discovery = __esm({
3159
3225
  const includeSchemas = c.req.query("schemas") === "true";
3160
3226
  const includeExamples = c.req.query("examples") === "true";
3161
3227
  const format = Container.getAdapter().name;
3162
- const discovery = new PluginDiscoveryService2({
3228
+ const discovery = new PluginDiscoveryService3({
3163
3229
  maxDepth: 10,
3164
3230
  includeNodeModules: false,
3165
3231
  verbose: false
@@ -3191,7 +3257,7 @@ var init_discovery = __esm({
3191
3257
  discoveryRouter.get("/documents", async (c) => {
3192
3258
  try {
3193
3259
  const format = Container.getAdapter().name;
3194
- const discovery = new PluginDiscoveryService2({
3260
+ const discovery = new PluginDiscoveryService3({
3195
3261
  maxDepth: 10,
3196
3262
  includeNodeModules: false,
3197
3263
  verbose: false
@@ -3203,10 +3269,24 @@ var init_discovery = __esm({
3203
3269
  return c.json({ success: false, error: error.message }, 500);
3204
3270
  }
3205
3271
  });
3272
+ discoveryRouter.get("/blocks", async (c) => {
3273
+ try {
3274
+ const format = Container.getAdapter().name;
3275
+ const references = await discoverBlockReferences(format);
3276
+ return c.json({
3277
+ success: true,
3278
+ data: references,
3279
+ count: references.length
3280
+ });
3281
+ } catch (error) {
3282
+ logger.error("Block discovery failed", { error: error.message });
3283
+ return c.json({ success: false, error: error.message }, 500);
3284
+ }
3285
+ });
3206
3286
  discoveryRouter.get("/themes", async (c) => {
3207
3287
  try {
3208
3288
  const format = Container.getAdapter().name;
3209
- const discovery = new PluginDiscoveryService2({
3289
+ const discovery = new PluginDiscoveryService3({
3210
3290
  maxDepth: 10,
3211
3291
  includeNodeModules: false,
3212
3292
  verbose: false
@@ -3241,7 +3321,7 @@ var init_discovery = __esm({
3241
3321
  try {
3242
3322
  const pluginName = c.req.param("name");
3243
3323
  const format = Container.getAdapter().name;
3244
- const discovery = new PluginDiscoveryService2({
3324
+ const discovery = new PluginDiscoveryService3({
3245
3325
  maxDepth: 10,
3246
3326
  includeNodeModules: false,
3247
3327
  verbose: false
@@ -3261,7 +3341,7 @@ var init_discovery = __esm({
3261
3341
  413
3262
3342
  );
3263
3343
  }
3264
- return c.text(await readFile(plugin.filePath, "utf-8"));
3344
+ return c.text(await readFile2(plugin.filePath, "utf-8"));
3265
3345
  } catch (error) {
3266
3346
  logger.error("Plugin source read failed", { error: error.message });
3267
3347
  return c.json({ success: false, error: error.message }, 500);
@@ -3271,7 +3351,7 @@ var init_discovery = __esm({
3271
3351
  try {
3272
3352
  const pluginName = c.req.param("name");
3273
3353
  const format = Container.getAdapter().name;
3274
- const discovery = new PluginDiscoveryService2({
3354
+ const discovery = new PluginDiscoveryService3({
3275
3355
  maxDepth: 10,
3276
3356
  includeNodeModules: false,
3277
3357
  verbose: false
@@ -3306,7 +3386,7 @@ var init_discovery = __esm({
3306
3386
  try {
3307
3387
  const name = c.req.param("name");
3308
3388
  const format = Container.getAdapter().name;
3309
- const discovery = new PluginDiscoveryService2({
3389
+ const discovery = new PluginDiscoveryService3({
3310
3390
  maxDepth: 10,
3311
3391
  includeNodeModules: false,
3312
3392
  verbose: false
@@ -3322,7 +3402,7 @@ var init_discovery = __esm({
3322
3402
  try {
3323
3403
  const name = c.req.param("name");
3324
3404
  const format = Container.getAdapter().name;
3325
- const discovery = new PluginDiscoveryService2({
3405
+ const discovery = new PluginDiscoveryService3({
3326
3406
  maxDepth: 10,
3327
3407
  includeNodeModules: false,
3328
3408
  verbose: false
@@ -3507,10 +3587,10 @@ function resolvePromptsDir() {
3507
3587
  return candidates[0];
3508
3588
  }
3509
3589
  function readPromptFile(name) {
3510
- if (cache.has(name)) return cache.get(name);
3590
+ if (cache2.has(name)) return cache2.get(name);
3511
3591
  const filePath = join(PROMPTS_DIR, name);
3512
3592
  const content = readFileSync(filePath, "utf-8");
3513
- cache.set(name, content);
3593
+ cache2.set(name, content);
3514
3594
  return content;
3515
3595
  }
3516
3596
  function loadPrompt(name, vars = {}) {
@@ -3520,14 +3600,14 @@ function loadPrompt(name, vars = {}) {
3520
3600
  }
3521
3601
  return content;
3522
3602
  }
3523
- var __dirname2, PROMPTS_DIR, cache;
3603
+ var __dirname2, PROMPTS_DIR, cache2;
3524
3604
  var init_prompt_loader = __esm({
3525
3605
  "src/server/services/prompt-loader.ts"() {
3526
3606
  "use strict";
3527
3607
  init_esm_shims();
3528
3608
  __dirname2 = dirname2(fileURLToPath2(import.meta.url));
3529
3609
  PROMPTS_DIR = resolvePromptsDir();
3530
- cache = /* @__PURE__ */ new Map();
3610
+ cache2 = /* @__PURE__ */ new Map();
3531
3611
  }
3532
3612
  });
3533
3613
 
@@ -3536,6 +3616,7 @@ import { Hono as Hono4 } from "hono";
3536
3616
  import { streamText, convertToModelMessages } from "ai";
3537
3617
  import { claudeCode } from "ai-sdk-provider-claude-code";
3538
3618
  import { extractText as extractPdfText } from "unpdf";
3619
+ import { blockSlotFacts as blockSlotFacts2 } from "@json-to-office/shared";
3539
3620
  function sanitizeFilename(name) {
3540
3621
  return name.replace(/[[\]\n\r]/g, "_");
3541
3622
  }
@@ -3688,7 +3769,11 @@ function createAiRouter() {
3688
3769
  const hasActiveDoc = !hasSelection && activeDocument?.text;
3689
3770
  const isGenerate = !hasSelection && !hasActiveDoc;
3690
3771
  if (!isTheme && format === "pptx" && !hasSelection) {
3691
- systemPrompt += "\n\n" + loadPrompt("pptx-design.md");
3772
+ systemPrompt += "\n\n" + loadPrompt("pptx-design.md", {
3773
+ referenceBlocks: blockReferencesPrompt(
3774
+ await discoverBlockReferences("pptx")
3775
+ )
3776
+ });
3692
3777
  }
3693
3778
  if (hasSelection) {
3694
3779
  const ctx = context[0];
@@ -3699,7 +3784,7 @@ function createAiRouter() {
3699
3784
  selectedText: ctx.selectedText
3700
3785
  });
3701
3786
  } else if (hasActiveDoc) {
3702
- const pptxScope = format === "pptx" && !isTheme && (scope === "slides" || scope === "templates");
3787
+ const pptxScope = format === "pptx" && !isTheme && (scope === "slides" || scope === "blocks");
3703
3788
  let parsedDoc = null;
3704
3789
  if (pptxScope) {
3705
3790
  try {
@@ -3709,38 +3794,36 @@ function createAiRouter() {
3709
3794
  }
3710
3795
  if (pptxScope && parsedDoc) {
3711
3796
  const doc = parsedDoc;
3797
+ const blocks = doc.props?.blocks || {};
3798
+ const invoked = (slide) => (slide.children || []).filter((child) => child?.name === "block").map((child) => String(child.props?.ref ?? "?"));
3712
3799
  if (scope === "slides") {
3713
- const templatesSummary = (doc.props?.templates || []).map((m) => {
3714
- const phs = (m.placeholders || []).map((p) => {
3715
- const d = p.defaults ? ` \u2192 defaults: ${JSON.stringify(p.defaults)}` : "";
3716
- return ` - \`${p.name}\`${d}`;
3800
+ const blocksSummary = Object.entries(blocks).map(([name, definition]) => {
3801
+ const slots = Object.entries(definition.slots || {}).map(([slot, spec]) => {
3802
+ const facts = [spec.type, ...blockSlotFacts2(spec)];
3803
+ const description2 = spec.description ? `: ${spec.description}` : "";
3804
+ return ` - \`${slot}\` \u2014 ${facts.join(", ")}${description2}`;
3717
3805
  }).join("\n");
3718
- return `**${m.name}**
3719
- ${phs}`;
3806
+ const description = definition.description ? ` \u2014 ${definition.description}` : "";
3807
+ return `**${name}**${description}
3808
+ ${slots || " _No slots._"}`;
3720
3809
  }).join("\n\n");
3721
3810
  const slidesText = JSON.stringify(doc.children || [], null, 2);
3722
3811
  systemPrompt += "\n\n" + loadPrompt("instructions-edit-document-pptx-slides.md", {
3723
3812
  documentName: activeDocument.name || "untitled",
3724
- templatesSummary,
3813
+ blocksSummary: blocksSummary || "_No blocks defined yet._",
3725
3814
  slidesText
3726
3815
  });
3727
3816
  } else {
3728
- const templatesText = JSON.stringify(
3729
- doc.props?.templates || [],
3730
- null,
3731
- 2
3732
- );
3733
- const slidesSummary = (doc.children || []).map((s, i) => {
3734
- const template = s.props?.template || "(none)";
3735
- const phs = Object.keys(s.props?.placeholders || {}).join(
3736
- ", "
3737
- );
3738
- return ` ${i}: template=${template}, placeholders=[${phs}]`;
3817
+ const blocksText = JSON.stringify(blocks, null, 2);
3818
+ const slidesSummary = (doc.children || []).map((slide, index) => {
3819
+ const title = slide.props?.meta?.title ? ` "${slide.props.meta.title}"` : "";
3820
+ const refs = invoked(slide);
3821
+ return ` ${index}:${title} blocks=[${refs.join(", ")}]`;
3739
3822
  }).join("\n");
3740
- systemPrompt += "\n\n" + loadPrompt("instructions-edit-document-pptx-templates.md", {
3823
+ systemPrompt += "\n\n" + loadPrompt("instructions-edit-document-pptx-blocks.md", {
3741
3824
  documentName: activeDocument.name || "untitled",
3742
- templatesText,
3743
- slidesSummary
3825
+ blocksText,
3826
+ slidesSummary: slidesSummary || " _No slides yet._"
3744
3827
  });
3745
3828
  }
3746
3829
  } else {
@@ -3860,6 +3943,7 @@ var init_ai = __esm({
3860
3943
  init_esm_shims();
3861
3944
  init_ai_schema();
3862
3945
  init_prompt_loader();
3946
+ init_block_references();
3863
3947
  init_logger();
3864
3948
  init_rate_limit();
3865
3949
  init_config();
@@ -4735,7 +4819,7 @@ function createDevCommand(adapter) {
4735
4819
  }
4736
4820
 
4737
4821
  // src/cli.ts
4738
- var PACKAGE_VERSION = true ? "2.4.0" : "dev-mode";
4822
+ var PACKAGE_VERSION = true ? "3.0.0" : "dev-mode";
4739
4823
  var program = new Command2();
4740
4824
  program.name("jto").description("JSON to Office CLI - Generate .docx and .pptx from JSON").version(PACKAGE_VERSION);
4741
4825
  registerCoreCommands(program, {