markform 0.1.24 → 0.1.25
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 +54 -31
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +2 -2
- package/dist/bin.mjs +1 -1
- package/dist/{cli-B1DhFYBS.mjs → cli-B1T8kMFt.mjs} +85 -40
- package/dist/cli-B1T8kMFt.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/{coreTypes-GxzWNXap.d.mts → coreTypes-CxpqKpBA.d.mts} +45 -2
- package/dist/{coreTypes-CctFK6uE.mjs → coreTypes-DIv9Aabl.mjs} +19 -5
- package/dist/coreTypes-DIv9Aabl.mjs.map +1 -0
- package/dist/{fillRecord-DeqI2pQ5.d.mts → fillRecord-V3vlyobd.d.mts} +5 -1
- package/dist/{fillRecordRenderer-VBQ2vwPV.mjs → fillRecordRenderer-BqRPHPmE.mjs} +47 -15
- package/dist/fillRecordRenderer-BqRPHPmE.mjs.map +1 -0
- package/dist/index.d.mts +32 -4
- package/dist/index.mjs +4 -4
- package/dist/{prompts-BCnYaH4_.mjs → prompts-DaPKumGY.mjs} +114 -11
- package/dist/prompts-DaPKumGY.mjs.map +1 -0
- package/dist/render.d.mts +2 -2
- package/dist/render.mjs +1 -1
- package/dist/{session-BLjN3BkJ.mjs → session-BW9jtYNV.mjs} +2 -2
- package/dist/{session-BLjN3BkJ.mjs.map → session-BW9jtYNV.mjs.map} +1 -1
- package/dist/{session-D7C7IlEv.mjs → session-DHyTMP67.mjs} +1 -1
- package/dist/{shared-DtorFV21.mjs → shared-BLh342F5.mjs} +1 -1
- package/dist/{shared-CuSRYcIB.mjs → shared-BszoSkAO.mjs} +8 -8
- package/dist/{shared-CuSRYcIB.mjs.map → shared-BszoSkAO.mjs.map} +1 -1
- package/dist/{src-C5OWf1dL.mjs → src-DrXmaOWl.mjs} +155 -27
- package/dist/src-DrXmaOWl.mjs.map +1 -0
- package/docs/markform-apis.md +19 -7
- package/docs/markform-reference.md +247 -178
- package/docs/markform-spec.md +81 -33
- package/docs/skill/SKILL.md +62 -20
- package/examples/markform-demo-playbook.md +342 -0
- package/examples/parallel/parallel-research.form.md +2 -6
- package/examples/simple/simple-mock-filled.report.md +2 -2
- package/examples/simple/simple-skipped-filled.report.md +2 -2
- package/examples/twitter-thread/twitter-thread.form.md +5 -5
- package/package.json +1 -1
- package/dist/cli-B1DhFYBS.mjs.map +0 -1
- package/dist/coreTypes-CctFK6uE.mjs.map +0 -1
- package/dist/fillRecordRenderer-VBQ2vwPV.mjs.map +0 -1
- package/dist/prompts-BCnYaH4_.mjs.map +0 -1
- package/dist/src-C5OWf1dL.mjs.map +0 -1
- package/examples/startup-research/startup-research-mock-filled.form.md +0 -297
- package/examples/startup-research/startup-research.form.md +0 -181
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# Markform
|
|
2
2
|
|
|
3
|
-
[](https://x.com/ojoshe)
|
|
4
|
+
[](https://github.com/jlevy/markform/actions/workflows/ci.yml)
|
|
5
5
|
[](https://www.npmjs.com/package/markform)
|
|
6
|
-
[](https://x.com/ojoshe)
|
|
7
6
|
|
|
8
7
|
### What if your Markdown docs had an agent-friendly semantic API?
|
|
9
8
|
|
|
@@ -17,10 +16,10 @@ Humans can review or intervene at any point.
|
|
|
17
16
|
|
|
18
17
|
### Why forms?
|
|
19
18
|
|
|
20
|
-
For deep research or complex AI tasks, you need more than just prompts or
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
For deep research or complex AI tasks, you need more than just prompts or flow: you need
|
|
20
|
+
*structure*, which is precise control over agent output at every stage of a workflow.
|
|
21
|
+
A well-designed form combines instructions, structured data, and validations in one
|
|
22
|
+
place.
|
|
24
23
|
|
|
25
24
|
### How it Works
|
|
26
25
|
|
|
@@ -42,20 +41,24 @@ in one place.
|
|
|
42
41
|
|
|
43
42
|
### Useful details
|
|
44
43
|
|
|
45
|
-
- Markform syntax is a good source format: it is **token-efficient text** you can read,
|
|
46
|
-
version control and it is **ideal for context engineering** because it
|
|
47
|
-
document context, data schema, and memory (data filled so far).
|
|
44
|
+
- Markform syntax is a good source format: it is **token-efficient text** you can read,
|
|
45
|
+
diff, and version control and it is **ideal for context engineering** because it
|
|
46
|
+
combines document context, data schema, and memory (data filled so far).
|
|
48
47
|
|
|
49
|
-
- Structure is defined with HTML comment tags (`<!-- field -->`) that
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
- Structure is defined with HTML comment tags (`<!-- field -->`) that render invisibly
|
|
49
|
+
on GitHub, so **forms look like regular Markdown**. (Jinja-style tag syntax also works
|
|
50
|
+
if you prefer.)
|
|
52
51
|
|
|
53
|
-
-
|
|
54
|
-
|
|
52
|
+
- Form-filling can scale to **hundreds of fields** in a form filled by **dozens of
|
|
53
|
+
concurrent LLM requests** which makes it possible to systemetize large, complex
|
|
54
|
+
research processes or workflows.
|
|
55
|
+
(And **a fill record** of the form-filling process is kept, so you can see and debug
|
|
56
|
+
exactly how forms are filled by agents, tool usage, LLM call time, etc.)
|
|
55
57
|
|
|
56
|
-
- The CLI has a built-in web renderer, **`markform serve`**, for easy viewing and
|
|
57
|
-
of forms (including a form web UI, the form schema, and a waterfall-style
|
|
58
|
-
fill record, including performance details, which is useful for large,
|
|
58
|
+
- The CLI has a built-in web renderer, **`markform serve`**, for easy viewing and
|
|
59
|
+
debugging of forms (including a form web UI, the form schema, and a waterfall-style
|
|
60
|
+
overview of the fill record, including performance details, which is useful for large,
|
|
61
|
+
concurrently filled forms).
|
|
59
62
|
|
|
60
63
|
## Simple Example: Research a Movie
|
|
61
64
|
|
|
@@ -302,11 +305,34 @@ See [the FAQ](#faq) for more on the design.
|
|
|
302
305
|
|
|
303
306
|
## Quick Start
|
|
304
307
|
|
|
308
|
+
There are three ways to get started, from quickest to most thorough:
|
|
309
|
+
|
|
310
|
+
**1. Run an example automatically** — copy bundled forms and let an LLM fill one:
|
|
311
|
+
|
|
305
312
|
```bash
|
|
306
|
-
#
|
|
307
|
-
# Set OPENAI_API_KEY or ANTHROPIC_API_KEY (or put in .env) for research examples
|
|
313
|
+
# Set OPENAI_API_KEY or ANTHROPIC_API_KEY (or put in .env)
|
|
308
314
|
npx markform@latest examples
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Pick `movie-research-demo.form.md` for a quick demo.
|
|
318
|
+
|
|
319
|
+
**2. Agent-guided tour** — ask a coding agent (like Claude Code) to walk you through a
|
|
320
|
+
specific example step by step.
|
|
321
|
+
The agent copies the form, explains the structure, fills fields, validates, and exports:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
# List available examples
|
|
325
|
+
markform examples --list
|
|
326
|
+
# Copy one to work with
|
|
327
|
+
markform examples --name movie-research-demo
|
|
328
|
+
```
|
|
309
329
|
|
|
330
|
+
**3. End-to-end walkthrough** — have a coding agent follow the
|
|
331
|
+
[demo playbook](packages/markform/examples/markform-demo-playbook.md) to design a
|
|
332
|
+
research form from scratch, fill it with real data, validate, export, and browse.
|
|
333
|
+
This is the most thorough tour of all Markform features.
|
|
334
|
+
|
|
335
|
+
```bash
|
|
310
336
|
# Read the docs (tell your agents to run these; they are agent-friendly!)
|
|
311
337
|
npx markform # CLI help
|
|
312
338
|
npx markform readme # This file
|
|
@@ -314,10 +340,6 @@ npx markform docs # Quick reference for writing Markforms
|
|
|
314
340
|
npx markform spec # Read the full spec
|
|
315
341
|
```
|
|
316
342
|
|
|
317
|
-
The `markform examples` command copies some sample forms to `./forms` and prompts you to
|
|
318
|
-
fill in a form interactively and then optionally have an agent complete it.
|
|
319
|
-
Pick `movie-research-demo.form.md` for a quick example.
|
|
320
|
-
|
|
321
343
|
## Installation
|
|
322
344
|
|
|
323
345
|
Requires Node.js 20+.
|
|
@@ -333,8 +355,9 @@ npm install markform
|
|
|
333
355
|
### Use as a Claude Code Skill
|
|
334
356
|
|
|
335
357
|
If you install markform globally (`npm install -g markform`), you can tell Claude to run
|
|
336
|
-
`markform setup --auto` to install it as a Claude Code skill.
|
|
337
|
-
use markform commands when working with `.form.md` files in
|
|
358
|
+
`markform setup --auto` to install it as a Claude Code skill.
|
|
359
|
+
This teaches Claude how to use markform commands when working with `.form.md` files in
|
|
360
|
+
your project.
|
|
338
361
|
|
|
339
362
|
```bash
|
|
340
363
|
# Install as a Claude Code skill (non-interactive, for agents)
|
|
@@ -431,7 +454,7 @@ flowchart LR
|
|
|
431
454
|
subgraph ENGINE["<b>CORE TYPESCRIPT APIS</b><br/>Markdoc parser, serializer,<br/>patch application,<br/>validation (jiti for rules)"]
|
|
432
455
|
end
|
|
433
456
|
|
|
434
|
-
subgraph
|
|
457
|
+
subgraph PARSER["<b>PARSER</b><br/>Markform language<br/>parser/serializer"]
|
|
435
458
|
end
|
|
436
459
|
|
|
437
460
|
CLI --> ENGINE
|
|
@@ -439,7 +462,7 @@ flowchart LR
|
|
|
439
462
|
AGENT --> HARNESS
|
|
440
463
|
AGENT --> ENGINE
|
|
441
464
|
HARNESS --> ENGINE
|
|
442
|
-
ENGINE -->
|
|
465
|
+
ENGINE --> PARSER
|
|
443
466
|
end
|
|
444
467
|
|
|
445
468
|
SPEC ~~~ IMPL
|
|
@@ -454,7 +477,7 @@ flowchart LR
|
|
|
454
477
|
style CLI fill:#ffe8cc,stroke:#fb8500
|
|
455
478
|
style AGENT fill:#ffe8cc,stroke:#fb8500
|
|
456
479
|
style HARNESS fill:#ffe8cc,stroke:#fb8500
|
|
457
|
-
style
|
|
480
|
+
style PARSER fill:#ffe8cc,stroke:#fb8500
|
|
458
481
|
```
|
|
459
482
|
|
|
460
483
|
## CLI Commands
|
|
@@ -588,8 +611,8 @@ If unsure, try `gpt-5-mini` first as it’s fast and supports web search.
|
|
|
588
611
|
|
|
589
612
|
## Programmatic Usage
|
|
590
613
|
|
|
591
|
-
Markform exports a parsing engine, rendering functions, and AI SDK integration for use
|
|
592
|
-
your own applications.
|
|
614
|
+
Markform exports a parsing engine, rendering functions, and AI SDK integration for use
|
|
615
|
+
in your own applications.
|
|
593
616
|
|
|
594
617
|
### Basic Parsing
|
|
595
618
|
|
package/dist/ai-sdk.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { At as ParsedForm, Nt as PatchSchema, U as FieldResponse, Y as FormSchema, at as InspectResult, et as Id, gr as ValidatorRegistry, jt as Patch, r as ApplyResult } from "./coreTypes-
|
|
2
|
+
import { At as ParsedForm, Nt as PatchSchema, U as FieldResponse, Y as FormSchema, at as InspectResult, et as Id, gr as ValidatorRegistry, jt as Patch, r as ApplyResult } from "./coreTypes-CxpqKpBA.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
5
|
//#region src/integrations/toolTypes.d.ts
|
package/dist/ai-sdk.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import { R as PatchSchema } from "./coreTypes-
|
|
3
|
-
import { _ as inspect, m as applyPatches, p as findFieldById, s as getPatchFormatHint, u as getFieldIdFromRef, w as serializeForm } from "./prompts-
|
|
2
|
+
import { R as PatchSchema } from "./coreTypes-DIv9Aabl.mjs";
|
|
3
|
+
import { _ as inspect, m as applyPatches, p as findFieldById, s as getPatchFormatHint, u as getFieldIdFromRef, w as serializeForm } from "./prompts-DaPKumGY.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
//#region src/integrations/vercelAiSdkTools.ts
|
package/dist/bin.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
import { R as PatchSchema } from "./coreTypes-
|
|
3
|
-
import { $ as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN, E as serializeReport, H as AGENT_ROLE, K as DEFAULT_MAX_PATCHES_PER_TURN, Q as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, S as computeStructureSummary, T as serializeRawMarkdown, U as DEFAULT_FORMS_DIR, W as DEFAULT_MAX_ISSUES_PER_TURN, X as DEFAULT_PORT, Y as DEFAULT_MAX_TURNS, _ as inspect, _t as parseModelIdForDisplay, at as deriveExportPath, c as filterIssuesByOrder, ct as deriveSchemaPath, d as coerceInputContext, f as coerceToFieldPatch, ft as SUGGESTED_LLMS, gt as hasWebSearchSupport, h as getAllFields, it as USER_ROLE, k as validateSyntaxConsistency, l as filterIssuesByScope, lt as detectFileType, m as applyPatches, mt as formatSuggestedLlms, nt as MAX_FORMS_IN_MENU, ot as deriveFillRecordPath, p as findFieldById, pt as WEB_SEARCH_CONFIG, rt as REPORT_EXTENSION, st as deriveReportPath, u as getFieldIdFromRef, ut as parseRolesFlag, w as serializeForm, x as computeProgressSummary } from "./prompts-
|
|
4
|
-
import { C as getProviderInfo, D as createLiveAgent, E as buildMockWireFormat, H as parseForm, N as createHarness, O as FillRecordCollector, T as resolveModel, V as formToJsonSchema, _ as resolveHarnessConfig, g as formatFillRecordSummary, h as stripUnstableFillRecordFields, i as runResearch, j as createMockAgent, k as computeExecutionPlan, m as isEmptyFillRecord, n as isResearchForm, t as VERSION, v as fillForm, w as getProviderNames } from "./src-
|
|
5
|
-
import { n as serializeSession } from "./session-
|
|
6
|
-
import { _ as writeFile$1, a as formatPath, c as logError, d as logTiming, f as logVerbose, g as stripHtmlComments, h as shouldUseColors, i as formatOutput, l as logInfo, m as readFile$1, n as createSpinner, o as getCommandContext, p as logWarn, r as ensureFormsDir, s as logDryRun, t as OUTPUT_FORMATS, u as logSuccess } from "./shared-
|
|
7
|
-
import { a as renderJsonContent, c as renderViewContent, i as highlightYamlValue, l as renderYamlContent, o as renderMarkdownContent, r as renderFillRecordContent, s as renderSourceContent, u as escapeHtml } from "./fillRecordRenderer-
|
|
2
|
+
import { R as PatchSchema } from "./coreTypes-DIv9Aabl.mjs";
|
|
3
|
+
import { $ as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN, E as serializeReport, H as AGENT_ROLE, K as DEFAULT_MAX_PATCHES_PER_TURN, Q as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, S as computeStructureSummary, T as serializeRawMarkdown, U as DEFAULT_FORMS_DIR, W as DEFAULT_MAX_ISSUES_PER_TURN, X as DEFAULT_PORT, Y as DEFAULT_MAX_TURNS, _ as inspect, _t as parseModelIdForDisplay, at as deriveExportPath, c as filterIssuesByOrder, ct as deriveSchemaPath, d as coerceInputContext, f as coerceToFieldPatch, ft as SUGGESTED_LLMS, gt as hasWebSearchSupport, h as getAllFields, it as USER_ROLE, k as validateSyntaxConsistency, l as filterIssuesByScope, lt as detectFileType, m as applyPatches, mt as formatSuggestedLlms, nt as MAX_FORMS_IN_MENU, ot as deriveFillRecordPath, p as findFieldById, pt as WEB_SEARCH_CONFIG, rt as REPORT_EXTENSION, st as deriveReportPath, u as getFieldIdFromRef, ut as parseRolesFlag, w as serializeForm, x as computeProgressSummary } from "./prompts-DaPKumGY.mjs";
|
|
4
|
+
import { C as getProviderInfo, D as createLiveAgent, E as buildMockWireFormat, H as parseForm, N as createHarness, O as FillRecordCollector, T as resolveModel, V as formToJsonSchema, _ as resolveHarnessConfig, g as formatFillRecordSummary, h as stripUnstableFillRecordFields, i as runResearch, j as createMockAgent, k as computeExecutionPlan, m as isEmptyFillRecord, n as isResearchForm, t as VERSION, v as fillForm, w as getProviderNames } from "./src-DrXmaOWl.mjs";
|
|
5
|
+
import { n as serializeSession } from "./session-BW9jtYNV.mjs";
|
|
6
|
+
import { _ as writeFile$1, a as formatPath, c as logError, d as logTiming, f as logVerbose, g as stripHtmlComments, h as shouldUseColors, i as formatOutput, l as logInfo, m as readFile$1, n as createSpinner, o as getCommandContext, p as logWarn, r as ensureFormsDir, s as logDryRun, t as OUTPUT_FORMATS, u as logSuccess } from "./shared-BszoSkAO.mjs";
|
|
7
|
+
import { a as renderJsonContent, c as renderViewContent, i as highlightYamlValue, l as renderYamlContent, o as renderMarkdownContent, r as renderFillRecordContent, s as renderSourceContent, u as escapeHtml } from "./fillRecordRenderer-BqRPHPmE.mjs";
|
|
8
8
|
import Markdoc from "@markdoc/markdoc";
|
|
9
9
|
import YAML from "yaml";
|
|
10
10
|
import { Command } from "commander";
|
|
@@ -1026,6 +1026,12 @@ const EXAMPLE_DEFINITIONS = [
|
|
|
1026
1026
|
path: "simple/simple.form.md",
|
|
1027
1027
|
type: "fill"
|
|
1028
1028
|
},
|
|
1029
|
+
{
|
|
1030
|
+
id: "twitter-thread",
|
|
1031
|
+
filename: "twitter-thread.form.md",
|
|
1032
|
+
path: "twitter-thread/twitter-thread.form.md",
|
|
1033
|
+
type: "fill"
|
|
1034
|
+
},
|
|
1029
1035
|
{
|
|
1030
1036
|
id: "movie-deep-research",
|
|
1031
1037
|
filename: "movie-deep-research.form.md",
|
|
@@ -2436,18 +2442,38 @@ function registerRunCommand(program) {
|
|
|
2436
2442
|
*/
|
|
2437
2443
|
/**
|
|
2438
2444
|
* Print non-interactive list of examples.
|
|
2445
|
+
* Supports --format=json and --format=yaml via formatOutput().
|
|
2439
2446
|
*/
|
|
2440
|
-
function printExamplesList() {
|
|
2441
|
-
console.log(pc.bold("Available examples:\n"));
|
|
2447
|
+
function printExamplesList(ctx) {
|
|
2442
2448
|
const examples = getAllExamplesWithMetadata();
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2449
|
+
const output = formatOutput(ctx, examples.map((example) => ({
|
|
2450
|
+
id: example.id,
|
|
2451
|
+
filename: example.filename,
|
|
2452
|
+
type: example.type,
|
|
2453
|
+
title: example.title ?? example.id,
|
|
2454
|
+
description: example.description ?? ""
|
|
2455
|
+
})), (_data, useColors) => {
|
|
2456
|
+
const c = useColors ? pc : {
|
|
2457
|
+
bold: (s) => s,
|
|
2458
|
+
cyan: (s) => s,
|
|
2459
|
+
magenta: (s) => s,
|
|
2460
|
+
blue: (s) => s,
|
|
2461
|
+
dim: (s) => s
|
|
2462
|
+
};
|
|
2463
|
+
const lines = [c.bold("Available examples:"), ""];
|
|
2464
|
+
for (const example of examples) {
|
|
2465
|
+
const typeLabel = example.type === "research" ? c.magenta("[research]") : c.blue("[fill]");
|
|
2466
|
+
lines.push(` ${c.cyan(example.id)} ${typeLabel}`);
|
|
2467
|
+
lines.push(` ${c.bold(example.title ?? example.id)}`);
|
|
2468
|
+
lines.push(` ${example.description ?? "No description"}`);
|
|
2469
|
+
lines.push(` Source: ${formatPath(getExamplePath(example.id))}`);
|
|
2470
|
+
lines.push("");
|
|
2471
|
+
}
|
|
2472
|
+
lines.push(c.dim("Tip: For a comprehensive end-to-end walkthrough, ask your coding agent"));
|
|
2473
|
+
lines.push(c.dim("to run the Markform QA playbook (tests/qa/markform-full-walkthrough.qa.md)."));
|
|
2474
|
+
return lines.join("\n");
|
|
2475
|
+
});
|
|
2476
|
+
console.log(output);
|
|
2451
2477
|
}
|
|
2452
2478
|
/**
|
|
2453
2479
|
* Copy an example form to the forms directory.
|
|
@@ -2588,7 +2614,7 @@ function registerExamplesCommand(program) {
|
|
|
2588
2614
|
const ctx = getCommandContext(cmd);
|
|
2589
2615
|
try {
|
|
2590
2616
|
if (options.list) {
|
|
2591
|
-
printExamplesList();
|
|
2617
|
+
printExamplesList(ctx);
|
|
2592
2618
|
return;
|
|
2593
2619
|
}
|
|
2594
2620
|
const formsDir = getFormsDir(ctx.formsDir);
|
|
@@ -4115,13 +4141,18 @@ function openBrowser(url) {
|
|
|
4115
4141
|
/**
|
|
4116
4142
|
* Build tabs for a form file.
|
|
4117
4143
|
* All tabs are always present - content is generated dynamically from the form.
|
|
4118
|
-
* Tab order:
|
|
4144
|
+
* Tab order: Form, Report, Edit, Source, Values, Schema, Fill Record (if sidecar exists)
|
|
4119
4145
|
*/
|
|
4120
4146
|
function buildFormTabs(formPath) {
|
|
4121
4147
|
const tabs = [
|
|
4122
4148
|
{
|
|
4123
4149
|
id: "view",
|
|
4124
|
-
label: "
|
|
4150
|
+
label: "Form",
|
|
4151
|
+
path: null
|
|
4152
|
+
},
|
|
4153
|
+
{
|
|
4154
|
+
id: "report",
|
|
4155
|
+
label: "Report",
|
|
4125
4156
|
path: null
|
|
4126
4157
|
},
|
|
4127
4158
|
{
|
|
@@ -4134,11 +4165,6 @@ function buildFormTabs(formPath) {
|
|
|
4134
4165
|
label: "Source",
|
|
4135
4166
|
path: formPath
|
|
4136
4167
|
},
|
|
4137
|
-
{
|
|
4138
|
-
id: "report",
|
|
4139
|
-
label: "Report",
|
|
4140
|
-
path: null
|
|
4141
|
-
},
|
|
4142
4168
|
{
|
|
4143
4169
|
id: "values",
|
|
4144
4170
|
label: "Values",
|
|
@@ -5067,10 +5093,10 @@ function renderFormHtml(form, tabs) {
|
|
|
5067
5093
|
if (response.ok) {
|
|
5068
5094
|
tabCache[tabId] = await response.text();
|
|
5069
5095
|
} else {
|
|
5070
|
-
tabCache[tabId] = '<div class="error">
|
|
5096
|
+
tabCache[tabId] = '<div class="error">No content available for this tab.</div>';
|
|
5071
5097
|
}
|
|
5072
5098
|
} catch (err) {
|
|
5073
|
-
tabCache[tabId] = '<div class="error">
|
|
5099
|
+
tabCache[tabId] = '<div class="error">No content available for this tab.</div>';
|
|
5074
5100
|
}
|
|
5075
5101
|
}
|
|
5076
5102
|
tabViewContent.innerHTML = tabCache[tabId];
|
|
@@ -5087,10 +5113,10 @@ function renderFormHtml(form, tabs) {
|
|
|
5087
5113
|
if (response.ok) {
|
|
5088
5114
|
tabCache[tabId] = await response.text();
|
|
5089
5115
|
} else {
|
|
5090
|
-
tabCache[tabId] = '<div class="error">
|
|
5116
|
+
tabCache[tabId] = '<div class="error">No content available for this tab.</div>';
|
|
5091
5117
|
}
|
|
5092
5118
|
} catch (err) {
|
|
5093
|
-
tabCache[tabId] = '<div class="error">
|
|
5119
|
+
tabCache[tabId] = '<div class="error">No content available for this tab.</div>';
|
|
5094
5120
|
}
|
|
5095
5121
|
}
|
|
5096
5122
|
tabOtherContent.innerHTML = tabCache[tabId];
|
|
@@ -5098,20 +5124,34 @@ function renderFormHtml(form, tabs) {
|
|
|
5098
5124
|
}
|
|
5099
5125
|
}
|
|
5100
5126
|
|
|
5127
|
+
// Navigate to a tab by id, updating the button state and hash
|
|
5128
|
+
let navigating = false;
|
|
5129
|
+
async function navigateToTab(tabId) {
|
|
5130
|
+
navigating = true;
|
|
5131
|
+
tabButtons.forEach(b => b.classList.remove('active'));
|
|
5132
|
+
const btn = document.querySelector('[data-tab="' + tabId + '"]');
|
|
5133
|
+
if (btn) btn.classList.add('active');
|
|
5134
|
+
location.hash = tabId;
|
|
5135
|
+
await showTab(tabId);
|
|
5136
|
+
navigating = false;
|
|
5137
|
+
}
|
|
5138
|
+
|
|
5101
5139
|
tabButtons.forEach(btn => {
|
|
5102
5140
|
btn.addEventListener('click', async () => {
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
// Update active button
|
|
5106
|
-
tabButtons.forEach(b => b.classList.remove('active'));
|
|
5107
|
-
btn.classList.add('active');
|
|
5108
|
-
|
|
5109
|
-
await showTab(tabId);
|
|
5141
|
+
await navigateToTab(btn.dataset.tab);
|
|
5110
5142
|
});
|
|
5111
5143
|
});
|
|
5112
5144
|
|
|
5113
|
-
//
|
|
5114
|
-
|
|
5145
|
+
// Handle hash-based navigation (back/forward, direct URL)
|
|
5146
|
+
window.addEventListener('hashchange', () => {
|
|
5147
|
+
if (navigating) return;
|
|
5148
|
+
const hash = window.location.hash.slice(1);
|
|
5149
|
+
if (hash) navigateToTab(hash);
|
|
5150
|
+
});
|
|
5151
|
+
|
|
5152
|
+
// Load initial tab from hash or default to Form (view) tab
|
|
5153
|
+
const initialTab = window.location.hash.slice(1) || 'view';
|
|
5154
|
+
navigateToTab(initialTab);
|
|
5115
5155
|
|
|
5116
5156
|
// URL copy tooltip functionality - initialize once
|
|
5117
5157
|
(function initUrlCopyTooltip() {
|
|
@@ -5870,9 +5910,9 @@ function registerResearchCommand(program) {
|
|
|
5870
5910
|
console.log(` ${formPath} ${pc.dim("(filled markform source)")}`);
|
|
5871
5911
|
console.log(` ${schemaPath} ${pc.dim("(JSON Schema)")}`);
|
|
5872
5912
|
if (options.transcript && result.transcript) {
|
|
5873
|
-
const { serializeSession } = await import("./session-
|
|
5913
|
+
const { serializeSession } = await import("./session-DHyTMP67.mjs");
|
|
5874
5914
|
const transcriptPath = outputPath.replace(/\.form\.md$/, ".session.yaml");
|
|
5875
|
-
const { writeFile } = await import("./shared-
|
|
5915
|
+
const { writeFile } = await import("./shared-BLh342F5.mjs");
|
|
5876
5916
|
await writeFile(transcriptPath, serializeSession(result.transcript));
|
|
5877
5917
|
logInfo(ctx, `Transcript: ${transcriptPath}`);
|
|
5878
5918
|
}
|
|
@@ -6123,6 +6163,11 @@ function registerSetCommand(program) {
|
|
|
6123
6163
|
for (const rp of applyResult.rejectedPatches) logError(` ${rp.message}`);
|
|
6124
6164
|
process.exit(1);
|
|
6125
6165
|
}
|
|
6166
|
+
if (!(Boolean(options.clear) || Boolean(options.skip) || Boolean(options.abort) || options.delete !== void 0)) {
|
|
6167
|
+
const patchedFieldIds = new Set(patches.map((p) => "fieldId" in p ? p.fieldId : "").filter(Boolean));
|
|
6168
|
+
const relevantIssues = applyResult.issues.filter((i) => i.reason === "validation_error" && patchedFieldIds.has(i.ref));
|
|
6169
|
+
for (const issue of relevantIssues) logWarn(ctx, issue.message);
|
|
6170
|
+
}
|
|
6126
6171
|
if (options.report) {
|
|
6127
6172
|
const output = formatOutput(ctx, {
|
|
6128
6173
|
apply_status: applyResult.applyStatus,
|
|
@@ -6631,4 +6676,4 @@ async function runCli() {
|
|
|
6631
6676
|
|
|
6632
6677
|
//#endregion
|
|
6633
6678
|
export { runCli as t };
|
|
6634
|
-
//# sourceMappingURL=cli-
|
|
6679
|
+
//# sourceMappingURL=cli-B1T8kMFt.mjs.map
|