markform 0.1.20 → 0.1.22
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 +44 -12
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +2 -2
- package/dist/{apply-DIvm1b1s.mjs → apply-C7mO7VkZ.mjs} +158 -95
- package/dist/apply-C7mO7VkZ.mjs.map +1 -0
- package/dist/bin.mjs +1 -1
- package/dist/{cli-FFMoEhFS.mjs → cli-C8F9yDsv.mjs} +102 -1225
- package/dist/cli-C8F9yDsv.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/{coreTypes-CkxML8g2.d.mts → coreTypes-BlsJkU1w.d.mts} +28 -2
- package/dist/{coreTypes-CPKXf2dc.mjs → coreTypes-CTLr-NGd.mjs} +24 -3
- package/dist/coreTypes-CTLr-NGd.mjs.map +1 -0
- package/dist/fillRecord-DTl5lnK0.d.mts +345 -0
- package/dist/fillRecordRenderer-CruJrLkj.mjs +1256 -0
- package/dist/fillRecordRenderer-CruJrLkj.mjs.map +1 -0
- package/dist/index.d.mts +22 -342
- package/dist/index.mjs +5 -5
- package/dist/render.d.mts +74 -0
- package/dist/render.mjs +4 -0
- package/dist/{session-CK0x28RO.mjs → session-BCcltrLA.mjs} +2 -2
- package/dist/{session-CK0x28RO.mjs.map → session-BCcltrLA.mjs.map} +1 -1
- package/dist/{session-ZHBi3LVQ.mjs → session-VeSkVrck.mjs} +1 -1
- package/dist/{shared-DwdyWmvE.mjs → shared-CsdT2T7k.mjs} +1 -1
- package/dist/{shared-DwdyWmvE.mjs.map → shared-CsdT2T7k.mjs.map} +1 -1
- package/dist/{shared-BTR35aMz.mjs → shared-fb0nkzQi.mjs} +1 -1
- package/dist/{src-wR7GoftB.mjs → src-CbRnGzMK.mjs} +205 -138
- package/dist/src-CbRnGzMK.mjs.map +1 -0
- package/dist/urlFormat-lls7CsEP.mjs +71 -0
- package/dist/urlFormat-lls7CsEP.mjs.map +1 -0
- package/docs/markform-apis.md +53 -0
- package/examples/movie-research/movie-deep-research-mock-filled.form.md +320 -343
- package/examples/movie-research/movie-deep-research.form.md +273 -308
- package/examples/movie-research/movie-research-demo.form.md +27 -41
- package/examples/parallel/parallel-research.form.md +33 -29
- package/examples/parallel/parallel-research.mock.filled.form.md +88 -0
- package/examples/rejection-test/rejection-test-mock-filled.form.md +21 -16
- package/examples/rejection-test/rejection-test-mock-filled.schema.json +1 -1
- package/examples/rejection-test/rejection-test.form.md +17 -15
- package/examples/rejection-test/rejection-test.session.yaml +88 -60
- package/examples/simple/simple-mock-filled.form.md +113 -126
- package/examples/simple/simple-mock-filled.schema.json +2 -3
- package/examples/simple/simple-skipped-filled.form.md +112 -129
- package/examples/simple/simple-skipped-filled.report.md +8 -8
- package/examples/simple/simple-skipped-filled.schema.json +2 -3
- package/examples/simple/simple-tags-syntax.form.md +32 -0
- package/examples/simple/simple-with-skips.session.yaml +663 -627
- package/examples/simple/simple.form.md +97 -113
- package/examples/simple/simple.schema.json +2 -3
- package/examples/simple/simple.session.yaml +663 -627
- package/examples/startup-deep-research/startup-deep-research.form.md +191 -235
- package/examples/startup-research/startup-research-mock-filled.form.md +128 -147
- package/examples/startup-research/startup-research.form.md +90 -129
- package/examples/twitter-thread/twitter-thread.form.md +373 -0
- package/package.json +5 -1
- package/dist/apply-DIvm1b1s.mjs.map +0 -1
- package/dist/cli-FFMoEhFS.mjs.map +0 -1
- package/dist/coreTypes-CPKXf2dc.mjs.map +0 -1
- package/dist/src-wR7GoftB.mjs.map +0 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/utils/urlFormat.ts
|
|
3
|
+
/**
|
|
4
|
+
* Create a friendly abbreviated display name for a URL.
|
|
5
|
+
* - Drops "www." prefix from domain
|
|
6
|
+
* - Adds first portion of path (up to maxPathChars) if present
|
|
7
|
+
* - Adds ellipsis (…) if path is truncated
|
|
8
|
+
*
|
|
9
|
+
* @param url - The URL to abbreviate
|
|
10
|
+
* @param maxPathChars - Maximum characters to include from the path (default: 12)
|
|
11
|
+
* @returns Friendly abbreviated URL (e.g., "example.com/docs/api…")
|
|
12
|
+
*/
|
|
13
|
+
function friendlyUrlAbbrev(url, maxPathChars = 12) {
|
|
14
|
+
try {
|
|
15
|
+
const parsed = new URL(url);
|
|
16
|
+
let hostname = parsed.hostname;
|
|
17
|
+
if (hostname.startsWith("www.")) hostname = hostname.slice(4);
|
|
18
|
+
const path = parsed.pathname.slice(1);
|
|
19
|
+
if (!path) return hostname;
|
|
20
|
+
if (path.length <= maxPathChars) return `${hostname}/${path}`;
|
|
21
|
+
return `${hostname}/${path.slice(0, maxPathChars)}…`;
|
|
22
|
+
} catch {
|
|
23
|
+
let result = url;
|
|
24
|
+
result = result.replace(/^https?:\/\//, "");
|
|
25
|
+
result = result.replace(/^www\./, "");
|
|
26
|
+
const maxLen = 30;
|
|
27
|
+
if (result.length > maxLen) return result.slice(0, maxLen) + "…";
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Format a URL as a markdown link with a friendly abbreviated display text.
|
|
33
|
+
* The full URL is preserved as the link target.
|
|
34
|
+
*
|
|
35
|
+
* @param url - The URL to format
|
|
36
|
+
* @returns Markdown link in format [friendly-abbrev](url)
|
|
37
|
+
*/
|
|
38
|
+
function formatUrlAsMarkdownLink(url) {
|
|
39
|
+
return `[${friendlyUrlAbbrev(url)}](${url})`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Format bare URLs in text as HTML links with abbreviated display text.
|
|
43
|
+
* Also handles markdown-style links [text](url) for consistency.
|
|
44
|
+
*
|
|
45
|
+
* Processing order:
|
|
46
|
+
* 1. Escape all HTML to prevent XSS
|
|
47
|
+
* 2. Convert markdown links [text](url) to <a> tags
|
|
48
|
+
* 3. Convert bare URLs (not already in links) to <a> tags with abbreviated display
|
|
49
|
+
*
|
|
50
|
+
* @param text - The raw text containing URLs (will be HTML-escaped)
|
|
51
|
+
* @param escapeHtml - Function to escape HTML entities
|
|
52
|
+
* @returns HTML-safe text with URLs converted to <a> tags
|
|
53
|
+
*/
|
|
54
|
+
function formatBareUrlsAsHtmlLinks(text, escapeHtml) {
|
|
55
|
+
let result = escapeHtml(text);
|
|
56
|
+
result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, linkText, url) => {
|
|
57
|
+
const cleanUrl = url.replace(/&/g, "&");
|
|
58
|
+
return `<a href="${escapeHtml(cleanUrl)}" target="_blank" class="url-link" data-url="${escapeHtml(cleanUrl)}">${linkText}</a>`;
|
|
59
|
+
});
|
|
60
|
+
result = result.replace(/(?<!href="|data-url="|">)(?:https?:\/\/|www\.)[^\s<>"]+(?<![.,;:!?'")])/g, (url) => {
|
|
61
|
+
const cleanUrl = url.replace(/&/g, "&");
|
|
62
|
+
const fullUrl = cleanUrl.startsWith("www.") ? `https://${cleanUrl}` : cleanUrl;
|
|
63
|
+
const display = friendlyUrlAbbrev(fullUrl);
|
|
64
|
+
return `<a href="${escapeHtml(fullUrl)}" target="_blank" class="url-link" data-url="${escapeHtml(fullUrl)}">${escapeHtml(display)}</a>`;
|
|
65
|
+
});
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
export { formatUrlAsMarkdownLink as n, friendlyUrlAbbrev as r, formatBareUrlsAsHtmlLinks as t };
|
|
71
|
+
//# sourceMappingURL=urlFormat-lls7CsEP.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urlFormat-lls7CsEP.mjs","names":[],"sources":["../src/utils/urlFormat.ts"],"sourcesContent":["/**\n * URL formatting utilities for display and markdown output.\n */\n\n/**\n * Extract the domain (hostname) from a URL.\n * Returns the original string if parsing fails.\n *\n * @param url - The URL to extract the domain from\n * @returns The domain (e.g., \"example.com\") or the original string if invalid\n */\nexport function extractDomain(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.hostname;\n } catch {\n // If URL parsing fails, try to extract domain-like pattern\n const match = /^(?:https?:\\/\\/)?(?:www\\.)?([^/\\s]+)/i.exec(url);\n if (match?.[1]) {\n return match[1];\n }\n // Return original if we can't extract a domain\n return url;\n }\n}\n\n/**\n * Create a friendly abbreviated display name for a URL.\n * - Drops \"www.\" prefix from domain\n * - Adds first portion of path (up to maxPathChars) if present\n * - Adds ellipsis (…) if path is truncated\n *\n * @param url - The URL to abbreviate\n * @param maxPathChars - Maximum characters to include from the path (default: 12)\n * @returns Friendly abbreviated URL (e.g., \"example.com/docs/api…\")\n */\nexport function friendlyUrlAbbrev(url: string, maxPathChars = 12): string {\n try {\n const parsed = new URL(url);\n // Remove www. prefix from hostname\n let hostname = parsed.hostname;\n if (hostname.startsWith('www.')) {\n hostname = hostname.slice(4);\n }\n\n // Get path without leading slash, excluding query string and hash\n const path = parsed.pathname.slice(1);\n if (!path) {\n return hostname;\n }\n\n // Include path up to maxPathChars\n if (path.length <= maxPathChars) {\n return `${hostname}/${path}`;\n }\n\n // Truncate path and add ellipsis\n return `${hostname}/${path.slice(0, maxPathChars)}…`;\n } catch {\n // If URL parsing fails, try basic cleanup\n let result = url;\n // Remove protocol\n result = result.replace(/^https?:\\/\\//, '');\n // Remove www.\n result = result.replace(/^www\\./, '');\n // Truncate if too long\n const maxLen = 30;\n if (result.length > maxLen) {\n return result.slice(0, maxLen) + '…';\n }\n return result;\n }\n}\n\n/**\n * Format a URL as a markdown link with a friendly abbreviated display text.\n * The full URL is preserved as the link target.\n *\n * @param url - The URL to format\n * @returns Markdown link in format [friendly-abbrev](url)\n */\nexport function formatUrlAsMarkdownLink(url: string): string {\n const display = friendlyUrlAbbrev(url);\n return `[${display}](${url})`;\n}\n\n/**\n * Check if a string looks like a URL.\n *\n * @param str - The string to check\n * @returns true if the string appears to be a URL\n */\nexport function isUrl(str: string): boolean {\n // Check for common URL patterns\n if (str.startsWith('http://') || str.startsWith('https://')) {\n return true;\n }\n // Check for www. prefix\n if (str.startsWith('www.')) {\n return true;\n }\n return false;\n}\n\n/**\n * Format bare URLs in text as HTML links with abbreviated display text.\n * Also handles markdown-style links [text](url) for consistency.\n *\n * Processing order:\n * 1. Escape all HTML to prevent XSS\n * 2. Convert markdown links [text](url) to <a> tags\n * 3. Convert bare URLs (not already in links) to <a> tags with abbreviated display\n *\n * @param text - The raw text containing URLs (will be HTML-escaped)\n * @param escapeHtml - Function to escape HTML entities\n * @returns HTML-safe text with URLs converted to <a> tags\n */\nexport function formatBareUrlsAsHtmlLinks(text: string, escapeHtml: (s: string) => string): string {\n // SECURITY: Escape the entire text first to prevent XSS\n let result = escapeHtml(text);\n\n // Convert markdown links [text](url) to <a> tags\n // After escaping, we need to unescape & back to & for URLs\n result = result.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_match, linkText: string, url: string) => {\n const cleanUrl = url.replace(/&/g, '&');\n return `<a href=\"${escapeHtml(cleanUrl)}\" target=\"_blank\" class=\"url-link\" data-url=\"${escapeHtml(cleanUrl)}\">${linkText}</a>`;\n });\n\n // Convert bare URLs to <a> tags with abbreviated display\n // Uses negative lookbehind to skip URLs that are:\n // - Inside href=\"\" or data-url=\"\" attributes\n // - Inside anchor tag content (preceded by \">)\n // Pattern matches http://, https://, www. URLs\n result = result.replace(\n /(?<!href=\"|data-url=\"|\">)(?:https?:\\/\\/|www\\.)[^\\s<>\"]+(?<![.,;:!?'\")])/g,\n (url: string) => {\n // Unescape & back to & for the actual URL\n const cleanUrl = url.replace(/&/g, '&');\n // Normalize www. URLs to have https://\n const fullUrl = cleanUrl.startsWith('www.') ? `https://${cleanUrl}` : cleanUrl;\n const display = friendlyUrlAbbrev(fullUrl);\n return `<a href=\"${escapeHtml(fullUrl)}\" target=\"_blank\" class=\"url-link\" data-url=\"${escapeHtml(fullUrl)}\">${escapeHtml(display)}</a>`;\n },\n );\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;AAoCA,SAAgB,kBAAkB,KAAa,eAAe,IAAY;AACxE,KAAI;EACF,MAAM,SAAS,IAAI,IAAI,IAAI;EAE3B,IAAI,WAAW,OAAO;AACtB,MAAI,SAAS,WAAW,OAAO,CAC7B,YAAW,SAAS,MAAM,EAAE;EAI9B,MAAM,OAAO,OAAO,SAAS,MAAM,EAAE;AACrC,MAAI,CAAC,KACH,QAAO;AAIT,MAAI,KAAK,UAAU,aACjB,QAAO,GAAG,SAAS,GAAG;AAIxB,SAAO,GAAG,SAAS,GAAG,KAAK,MAAM,GAAG,aAAa,CAAC;SAC5C;EAEN,IAAI,SAAS;AAEb,WAAS,OAAO,QAAQ,gBAAgB,GAAG;AAE3C,WAAS,OAAO,QAAQ,UAAU,GAAG;EAErC,MAAM,SAAS;AACf,MAAI,OAAO,SAAS,OAClB,QAAO,OAAO,MAAM,GAAG,OAAO,GAAG;AAEnC,SAAO;;;;;;;;;;AAWX,SAAgB,wBAAwB,KAAqB;AAE3D,QAAO,IADS,kBAAkB,IAAI,CACnB,IAAI,IAAI;;;;;;;;;;;;;;;AAkC7B,SAAgB,0BAA0B,MAAc,YAA2C;CAEjG,IAAI,SAAS,WAAW,KAAK;AAI7B,UAAS,OAAO,QAAQ,6BAA6B,QAAQ,UAAkB,QAAgB;EAC7F,MAAM,WAAW,IAAI,QAAQ,UAAU,IAAI;AAC3C,SAAO,YAAY,WAAW,SAAS,CAAC,+CAA+C,WAAW,SAAS,CAAC,IAAI,SAAS;GACzH;AAOF,UAAS,OAAO,QACd,6EACC,QAAgB;EAEf,MAAM,WAAW,IAAI,QAAQ,UAAU,IAAI;EAE3C,MAAM,UAAU,SAAS,WAAW,OAAO,GAAG,WAAW,aAAa;EACtE,MAAM,UAAU,kBAAkB,QAAQ;AAC1C,SAAO,YAAY,WAAW,QAAQ,CAAC,+CAA+C,WAAW,QAAQ,CAAC,IAAI,WAAW,QAAQ,CAAC;GAErI;AAED,QAAO"}
|
package/docs/markform-apis.md
CHANGED
|
@@ -546,6 +546,59 @@ interface InjectHeaderIdsOptions {
|
|
|
546
546
|
}
|
|
547
547
|
```
|
|
548
548
|
|
|
549
|
+
## Rendering API
|
|
550
|
+
|
|
551
|
+
Import from the render subpath for HTML rendering functions that produce the same output
|
|
552
|
+
as `markform serve`:
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
import {
|
|
556
|
+
renderViewContent,
|
|
557
|
+
renderSourceContent,
|
|
558
|
+
renderMarkdownContent,
|
|
559
|
+
renderYamlContent,
|
|
560
|
+
renderJsonContent,
|
|
561
|
+
renderFillRecordContent,
|
|
562
|
+
FILL_RECORD_STYLES,
|
|
563
|
+
FILL_RECORD_SCRIPTS,
|
|
564
|
+
escapeHtml,
|
|
565
|
+
formatDuration,
|
|
566
|
+
formatTokens,
|
|
567
|
+
} from 'markform/render';
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
These functions produce HTML fragments (not full pages), so consumers can embed them in
|
|
571
|
+
their own page shell with their own layout, CSS reset, and surrounding UI.
|
|
572
|
+
|
|
573
|
+
### Content Renderers
|
|
574
|
+
|
|
575
|
+
| Function | Input | Description |
|
|
576
|
+
| --- | --- | --- |
|
|
577
|
+
| `renderViewContent(form)` | `ParsedForm` | Render a form as a read-only HTML view |
|
|
578
|
+
| `renderSourceContent(content)` | `string` | Render Jinja-style form source with syntax highlighting |
|
|
579
|
+
| `renderMarkdownContent(content)` | `string` | Render markdown as HTML |
|
|
580
|
+
| `renderYamlContent(content)` | `string` | Render YAML with syntax highlighting |
|
|
581
|
+
| `renderJsonContent(content)` | `string` | Render JSON with syntax highlighting |
|
|
582
|
+
| `renderFillRecordContent(record)` | `FillRecord` | Render a fill record as an interactive dashboard |
|
|
583
|
+
|
|
584
|
+
### CSS and JavaScript Constants
|
|
585
|
+
|
|
586
|
+
| Export | Description |
|
|
587
|
+
| --- | --- |
|
|
588
|
+
| `FILL_RECORD_STYLES` | `<style>` block with CSS for the fill record dashboard |
|
|
589
|
+
| `FILL_RECORD_SCRIPTS` | JavaScript providing `frShowTip()`, `frHideTip()`, `frCopyYaml()` for fill record interactivity |
|
|
590
|
+
|
|
591
|
+
Include `FILL_RECORD_STYLES` in your page `<head>` and `FILL_RECORD_SCRIPTS` in a
|
|
592
|
+
`<script>` tag when using `renderFillRecordContent()`.
|
|
593
|
+
|
|
594
|
+
### Utility Functions
|
|
595
|
+
|
|
596
|
+
| Function | Description |
|
|
597
|
+
| --- | --- |
|
|
598
|
+
| `escapeHtml(str)` | Escape HTML special characters |
|
|
599
|
+
| `formatDuration(ms)` | Format milliseconds as human-readable duration (e.g., `"1m 5s"`) |
|
|
600
|
+
| `formatTokens(count)` | Format token counts with k suffix (e.g., `"1.5k"`) |
|
|
601
|
+
|
|
549
602
|
## Type Exports
|
|
550
603
|
|
|
551
604
|
All Zod schemas and TypeScript types are exported from the main package:
|